Linux网络编程(六)——包裹函数
宗旨:技术的学习是有限的,分享的精神的无限的。
系统调用不能保证每次都成功,必须进行出错处理。包裹函数就是把一般函数加了出错处理。包裹函数首字母大写。
/************************************************************************* > File Name: wrap.h > Author: libang > Mail: [email protected] > Created Time: 2016年04月06日 星期三 17时23分35秒 ************************************************************************/ #ifndef WRAP_H #define WRAP_H #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/socket.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> void perr_exit(const char *s); int Accept(int fd,struct sockaddr *sa,socklen_t *salenptr); void Bind(int fd,const struct sockaddr* sa,socklen_t salen); void Connect(int fd,const struct sockaddr* sa,socklen_t salen); void Listen(int fd,int backlog); int Socket(int family,int type,int protocol); ssize_t Read(int fd,void *ptr,size_t nbytes); ssize_t Write(int fd,const void *ptr,size_t nbytes); ssize_t Readn(int fd,void *vptr,size_t n); ssize_t Writen(int fd,const void*vptr,size_t n); static ssize_t my_read(int fd,char *ptr); static Readline(int fd,void *vptr,size_t maxlen); void Close(int fd); #endif
/************************************************************************* > File Name: wrap.c > Author: libang > Mail: [email protected] > Created Time: 2016年04月06日 星期三 17时53分25秒 ************************************************************************/ #include "wrap.h" void perr_exit(const char *s) { perror(s); exit(1); } int Accept(int fd, struct sockaddr *sa, socklen_t* salenptr) { int newfd; again: if((newfd = accept(fd, sa, salenptr)) < 0) { if((errno == ECONNABORTED) || (errno == EINTR)) { goto again; } else { perr_exit("accept error"); } } return newfd; } void Bind(int fd, const struct sockaddr* sa, socklen_t salen) { if(bind(fd, sa, salen) < 0) { perr_exit("bind error"); } } void Connect(int fd, const struct sockaddr *sa, socklen_t salen) { if(connect(fd, sa, salen) < 0) { perr_exit("connect error"); } } void Listen(int fd, int backlog) { if(listen(fd, backlog) < 0) { perr_exit("listen error"); } } int Socket(int family, int type, int protocol) { int socketfd; if((socketfd = socket(family, type, protocol)) < 0) { perr_exit("socket error"); } return socketfd; } ssize_t Read(int fd, void *ptr, size_t nbytes) { ssize_t n; again: if((n = read(fd, ptr, nbytes)) == -1) { if(errno == EINTR) { goto again; } else { return -1; } } return n; } ssize_t Write(int fd, const void *ptr, size_t nbytes) { ssize_t n; again: if((n = write(fd, ptr, nbytes)) == -1) { if(errno == EINTR) { goto again; } else { return -1; } } return n; } ssize_t Readn(int fd, void *vptr, size_t n) { size_t nleft; ssize_t nread; char *ptr; ptr = vptr; nleft = n; while(nleft > 0) { if((nread = read(fd, ptr, nleft)) < 0) { if(errno == EINTR) { nread = 0; } else { return -1; } } else if(nread == 0) { break; } nleft -= nread; ptr += nread; } return (n - nleft); } ssize_t Writen(int fd, const void *vptr, size_t n) { size_t nleft; ssize_t nwritten; const char* ptr; ptr = vptr; nleft = n; while(nleft > 0) { if((nwritten = write(fd, ptr, nleft)) <= 0) { if(nwritten < 0 && errno == EINTR) { nwritten = 0; } else { return -1; } } nleft -= nwritten; ptr += nwritten; } return n; } static ssize_t my_read(int fd, char *ptr) { static int read_cnt; static char *read_ptr; static char read_buf[100]; if(read_cnt <= 0) { again: if((read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) { if(errno == EINTR) { goto again; } else { return -1; } } else if(read_cnt == 0) { return 0; } read_ptr = read_buf; } read_cnt--; *ptr = *read_ptr++; return 1; } ssize_t Readline(int fd, void *vptr, size_t maxlen) { ssize_t n, rc; char c, *ptr; ptr = vptr; for(n = 1; n < maxlen; n++) { if((rc = my_read(fd, &c)) == 1) { *ptr++ = c; if(c == '\n') { break; } } else if(rc == 0) { *ptr = 0; return n - 1; } else { return (n - 1); } } *ptr = 0; return n; } void Close(int fd) { if(close(fd) == -1) { perr_exit("close error"); } }
/************************************************************************* > File Name: server.c > Author: libang > Mail: [email protected] > Created Time: 2016年04月6日 星期日 23时51分26秒 ************************************************************************/ #include "wrap.h" #define MAXLINE 80 #define SERV_PORT 8000 int main(int argc,char *argv[]) { struct sockaddr_in servaddr,cliaddr; socklen_t cliaddr_len; int sockfd; char buf[MAXLINE]; char str[INET_ADDRSTRLEN];//系统定义的宏TCP:16 UDP:46 int i,n; /* 服务器端开始建立sockfd描述符 */ sockfd = Socket(AF_INET,SOCK_DGRAM,0);// AF_INET:IPV4;SOCK_STREAM:TCP /* 服务器端填充 sockaddr结构 */ bzero(&servaddr,sizeof(servaddr));// 初始化,置0 servaddr.sin_family = AF_INET; // Internet servaddr.sin_addr.s_addr = htonl(INADDR_ANY);// (将本机器上的long数据转化为网络上的long数据)和任何主机通信 //INADDR_ANY 表示可以接收任意IP地址的数据,即绑定到所有的IP //server_addr.sin_addr.s_addr=inet_addr("192.168.1.1"); //用于绑定到一个固定IP,inet_addr用于把数字加格式的ip转化为整形ip servaddr.sin_port = htons(SERV_PORT); // (将本机器上的short数据转化为网络上的short数据)端口号 /* 捆绑sockfd描述符到IP地址 */ Bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)); printf("Accept connections ...\n"); while(1) { cliaddr_len = sizeof(cliaddr);//地址长度 n = recvfrom(sockfd,buf,MAXLINE,0,(struct sockaddr *)&cliaddr,&cliaddr_len );//接收客户端信息到buf中 if(n == -1) perr_exit("recvfrom error"); printf("recvfrom from %s at PORT %d\n",inet_ntop(AF_INET,&cliaddr.sin_addr,str,sizeof(str)),ntohs(cliaddr.sin_port)); for(i=0;i<n;i++) buf[i] = toupper(buf[i]);//小写转大写 n = sendto(sockfd,buf,n,0,(struct sockaddr*)&cliaddr,sizeof(cliaddr));//把buf内容发送sockfd中发给客户端 if(n == -1) perr_exit("sendto error"); } return 0; }
/************************************************************************* > File Name: client.c > Author: libang > Mail: [email protected] > Created Time: 2016年04月6日 星期一 23时03分44秒 ************************************************************************/ #include "wrap.h" #define MAXLINE 80 #define SERV_PORT 8000 int main(int argc,char *argv[]) { struct sockaddr_in servaddr; int sockfd,n; char buf[MAXLINE]; char str[INET_ADDRSTRLEN];//系统定义的宏TCP:16 UDP:46 socklen_t servaddr_len; /* 服务器端开始建立sockfd描述符 */ sockfd = Socket(AF_INET,SOCK_DGRAM,0); /* 客户程序填充服务端的资料 */ bzero(&servaddr,sizeof(servaddr));// 初始化,置0 servaddr.sin_family = AF_INET; // IPV4 inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr);// IP地址 servaddr.sin_port = htons(SERV_PORT);// (将本机器上的short数据转化为网络上的short数据)端口号 while(fgets(buf,MAXLINE,stdin) != NULL)//从键盘输入内容 { /*发送buf到sockfd中*/ n = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)&servaddr,sizeof(servaddr)); if(n == -1) perr_exit("recvfrom error"); n = recvfrom(sockfd,buf,MAXLINE,0,NULL,0); if(n == -1) perr_exit("recvfrom error"); Write(STDOUT_FILENO,buf,n);//写到标准输出中 } Close(sockfd); return 0; }