#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; }