#include <sys/socket.h>
以太網中的字節序是大端的,所以相關的以太網的數據在小端機器上須要使用相關接口轉換爲以太網字節序。經常使用轉換工具函數:linux
//4字節整形變量主機字節序的轉換爲網絡字節序 uint32_t htonl(uint32_t hostint32); //2字節整形變量主機字節序的轉換爲網絡字節序 uint16_t htons(uint15_t hostint16); //和上面相反 uint32_t ntohl(uint32_t netint32); //和上面相反 uint32_t ntohl(uint32_t netint32);
//建立套接字 int socket(int domain,int type,int protocol); //將一個套接字和指定地址和端點關聯起來 int bind(int sockfd,const struct sockaddr * addr,socklen_t addrlen); //開始監聽這個套接字 int listen(int socket, int backlog); //向指定socket發起鏈接請求 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); //接收監聽到的一個socket鏈接請求 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); //經過socket 發送數據,地址是socket默認 ssize_t send(int sockfd, const void *buf, size_t len, int flags); //經過socket 接收數據,地址爲socket 默認 ssize_t recv(int sockfd, void *buf, size_t len, int flags); //經過socket 發送數據,地址是由參數指定 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen); //經過socket 接收數據,地址由參數指定 ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen); //經常使用在unix 域下的進程通信,發送數據 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); //經常使用在unix 域下的進程通信,接收數據 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); //獲取當前socket信息 int getsockname((int sockfd, const struct sockaddr *addr, socklen_t addrlen); //獲取原端socket信息(創建鏈接以後) int getpeername((int sockfd, const struct sockaddr *addr, socklen_t addrlen);
套接字關閉能夠像關閉一個文件的描述符同樣調用close()接口來關閉socket接口,除此以外還可使用shutdown接口進行更加細緻的關閉操做:編程
sockfd :sock描述符 how :SHUT_RDWR 讀寫兩端都關閉 : SHUT_WR 關閉寫端 : SHUT_RD 關閉讀端 返回值 :成功返回0 失敗返回-1 int shutdown(int sockfd,int how);
//描述網絡信息 struct sockaddr_in { s_add.sin_family = AF_INET; s_add.sin_port = htons(1040); s_add.sin_addr.s_addr = inet_addr("127.0.0.1"); };
//創建 IPv4域下的字節流服務的TCP協議的socket int sockfd_s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//將這個socket個特定地址何端口關聯起來 bind(sockfd_s,(struct sockaddr*)&s_add,sizeof(struct sockaddr_in))
//開始監聽 listen(sockfd_s,1)
//接受任意鏈接請求,返回能夠用來數據傳輸的socket描述符 accept(sockfd_s,NULL,NULL);
//創建 IPv4域下的字節流服務的TCP協議的socket int sockfd_s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//向制定地址和端口發起連接請求 connect(sockfd_c,(struct sockaddr*)&c_add,sizeof(c_add))
見文末api
獲取本地套接字信息
獲取遠端套接字信息(鏈接後)網絡
int setsockopr(int sockfd,int level,int option,void *val,socklen_t len);
int setsockopr(int sockfd,int level,int option,void *val);
是一些通信協議支持的可選功能,與普通數據相比其具備更高的優先級被傳輸。目前TCP的支持帶外數據傳輸的,僅支持一個字節的緊急數據。有些實現TCP的帶外數據還能夠產生SIGURG信號。還能夠經過下面的接口判斷是否有緊急數據,當有緊急數據時,返回1。dom
iny sockatmark(int sockfd);
基本上socket的異步IO和阻塞和非阻塞的處理和普通的文件基本相同,可是有一些區別的是,可是目前尚未完整的標準,視具體平臺的實現狀況。異步
int main(int argc,int *argv) { char *name,i; struct hostent* host; size_t len = sysconf(_SC_HOST_NAME_MAX); if(len>0){ name = malloc(len+1); }else{ name = malloc(1024); len = 1024; } printf("Buff size%ld\n",stdout->_IO_buf_end-stdout->_IO_buf_base); if(gethostname(name,len)<0){ printf("gethostname error!\n"); } host = gethostbyname(name); if(*host->h_aliases){ printf("%s\n%s\n%s\n%d\n", host->h_name,//host name *host->h_aliases, //host_name aliases (host->h_addrtype==AF_INET?"IP_V4":"IP_V6"), host->h_length); }else{ printf("%s\n%s\n%d\n", host->h_name, (host->h_addrtype==AF_INET?"IP_V4":"IP_V6"), host->h_length); } for(i=0;host->h_addr_list[i] != NULL;i++){ printf("%s\n",inet_ntoa(*(struct in_addr*)host->h_addr_list[i])); } printf("befor the fork call\n\n"); int pid = fork(); if(pid){ int status,temp=1; int sockfd_s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(sockfd_s<0){ goto fail; } if(setsockopt(sockfd_s,SOL_SOCKET,SO_REUSEADDR,&temp,sizeof(int)) < 0) { perror("setsockopt"); } struct sockaddr_in s_add; s_add.sin_family = AF_INET; s_add.sin_port = htons(1040); s_add.sin_addr.s_addr = inet_addr("127.0.0.1"); // inet_pton(AF_INET,"127.0.0.1",&s_add.sin_addr); if(bind(sockfd_s,(struct sockaddr*)&s_add,sizeof(s_add))<0){ printf("1\n"); goto fail; } if(listen(sockfd_s,1)<0){ goto fail; } int c_fd = accept(sockfd_s,NULL,NULL); if(c_fd < 0){ goto fail; } int len=sizeof(s_add); if(getpeername(c_fd,(struct sockaddr*)&s_add,&len)<0){ printf("2\n"); goto fail; } printf("server:\n%s\n%d\n",inet_ntoa(s_add.sin_addr),ntohs(s_add.sin_port)); if(c_fd){ while(1){ char buf[64]; recv(c_fd,buf,64,0); printf("%s\n",buf); sleep(1); } } fail: close(sockfd_s); perror(strerror(errno)); kill(pid,9); waitpid(pid,&status,0); printf("server end\n"); return 0; }else if(!pid){ sleep(3); int sockfd_c = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(sockfd_c<0){ goto fail_c; } struct sockaddr_in c_add; c_add.sin_family = AF_INET; c_add.sin_port = htons(1040); c_add.sin_addr.s_addr = inet_addr("127.0.0.1"); // inet_pton(AF_INET,"127.0.0.1",&c_add.sin_addr); if(connect(sockfd_c,(struct sockaddr*)&c_add,sizeof(c_add))){ goto fail_c; } struct sockaddr_in d_add; int len=sizeof(d_add); if(getpeername(sockfd_c,(struct sockaddr*)&d_add,&len)<0){ goto fail_c; } printf("cliens\n%s\n%d\n",inet_ntoa(d_add.sin_addr),ntohs(d_add.sin_port)); while(1) { send(sockfd_c,"hello word!\n",strlen("hello word!\n"),0); sleep(1); } fail_c: close(sockfd_c); perror(strerror(errno)); _exit(0); } return 0; }