linux下自定义协议防止粘包问题

目的:防止服务器与客户端常见的粘包问题
思路:自定义结构体,把发送数据帧的长度与数据帧进行分装,以防止客户端与服务器之间的粘包问题
服务器端代码:

/************************************************************************* > File Name: test.c > Author: kinght > Mail: zhjnight@163.com > Created Time: Wed 20 Jun 2018 06:58:02 PM PDT ************************************************************************/#include #include//connect,send,recv,setsockopt等 #include#include // sockaddr_in, "man 7 ip" ,htons #include //poll,pollfd #include//inet_addr,inet_aton #include //read,write #include //gethostbyname#include //perror #include #include //errno#include// memset #include #include #include #ifdef HAVE_NETINET_IN_H #include #endif#define ERR_EXIT(m)\ do\ {\ perror(m); \ exit(EXIT_FAILURE); \ }while(0)struct packet { int len; char buf[1024]; }; ssize_t readn(int fd,void *buf,size_t count) { //printf("%d\n",count); size_t nleft = count; ssize_t nread; char *bufp = (char*)buf; //fputs(bufp,stdout); while(nleft>0) { nread = read(fd,bufp,nleft); //printf("%d\n",nread); //fputs(bufp,stdout); if(nread <0) { if(errno = EINTR) { return -1; } } else if(nread == 0) { break; } else { bufp += nread; nleft -= nread; }} }ssize_t written(int fd,void *buf,size_t count) { //printf("%d",count); size_t nleft = count; ssize_t nwritten; char *bufp = (char*)buf; //fputs(bufp,stdout); while(nleft>0) { nwritten = write(fd,bufp,nleft); if(nwritten <0) { if(errno = EINTR) { return -1; } } else if(nwritten == 0) { continue; } else { bufp += nwritten; nleft= nleft -nwritten; //printf("%d",nleft); }} }void doServiceConn(int conn) { /*char recvbuf[1024]; while(true) { memset(recvbuf,0,sizeof(recvbuf)); int ret = readn(conn,recvbuf,4); if(ret == 0) { printf("client close"); break; } else if(ret == -1) { ERR_EXIT("read"); }written(conn,recvbuf,sizeof(recvbuf)); printf(recvbuf,stdout); }*/ struct packetrecvbuf; memset(&recvbuf,0,sizeof(recvbuf)); int n; while(true) { int ret = readn(conn,&recvbuf.len,4); if(ret == -1) ERR_EXIT("read"); else if(ret < 4) { printf("peer close"); break; } n= ntohl(recvbuf.len); ret = readn(conn,recvbuf.buf,n); if(ret == -1) { ERR_EXIT("read"); } else if(ret < n) { printf("client close"); break; } fputs(recvbuf.buf,stdout); written(conn,&recvbuf,4+n); } } int main(void) { int listenfd; if((listenfd =socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0) { ERR_EXIT("ERROR"); } struct sockaddr_in servaddr; memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family=AF_INET; servaddr.sin_port = htons(5188); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); int on = 1; if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))< 0) { ERR_EXIT("SETSOCKOPT"); } if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))< 0) { ERR_EXIT("error"); } if(listen(listenfd,SOMAXCONN)<0) { ERR_EXIT("listen"); } struct sockaddr_in peeraddr; socklen_t peerlen = sizeof(peeraddr); int conn; pid_t pid; while(1) { conn = accept(listenfd,(struct sockaddr*)&peeraddr,&peerlen); if(conn < 0) { ERR_EXIT("accept"); } printf("ip= %s,port = %d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port)); pid = fork(); if(pid == -1) ERR_EXIT("fork"); if(pid == 0) { close(listenfd); doServiceConn(conn); exit(EXIT_SUCCESS); } else { close(conn); } }return 0; }

【linux下自定义协议防止粘包问题】客户端代码:
/************************************************************************* > File Name: client.c > Author: kinght > Mail: zhjnight@163.com > Created Time: Wed 20 Jun 2018 06:58:02 PM PDT ************************************************************************/#include #include//connect,send,recv,setsockopt等 #include#include // sockaddr_in, "man 7 ip" ,htons #include //poll,pollfd #include//inet_addr,inet_aton #include //read,write #include //gethostbyname#include //perror #include #include //errno#include// memset #include #include #include #ifdef HAVE_NETINET_IN_H #include #endif#define ERR_EXIT(m)\ do\ {\ perror(m); \ exit(EXIT_FAILURE); \ }while(0)struct packet { int len; char buf[1024]; }; ssize_t readn(int fd,void *buf,size_t count) { size_t nleft = count; ssize_t nread; char *bufp = (char*)buf; while(nleft>0) { nread = read(fd,bufp,nleft); if(nread <0) { if(errno = EINTR) { return -1; } } else if(nread == 0) { break; } else { bufp += nread; nleft -= nread; }} }ssize_t written(int fd,void *buf,size_t count) { //printf("%d",count); size_t nleft = count; ssize_t nwritten; char *bufp = (char*)buf; //fputs(bufp,stdout); while(nleft>0) { nwritten = write(fd,bufp,nleft); if(nwritten <0) { if(errno = EINTR) { return -1; } } else if(nwritten == 0) { continue; } else { bufp += nwritten; nleft= nleft -nwritten; //printf("%d",nleft); }} }int main(void) { int sock; if((sock =socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0) { ERR_EXIT("ERROR"); } struct sockaddr_in servaddr; memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family=AF_INET; servaddr.sin_port = htons(5188); servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if(connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr))< 0) { ERR_EXIT("connect"); } //char sendbuf[1024]={0}; //char recvbuf[1024]={0}; struct packet sendbuf; struct packet recvbuf; memset(&sendbuf,0,sizeof(sendbuf)); memset(&recvbuf,0,sizeof(recvbuf)); int n; while(fgets(sendbuf.buf,sizeof(sendbuf.buf),stdin)!=NULL) { /*written(sock,sendbuf,strlen(sendbuf)); readn(sock,recvbuf,sizeof(recvbuf)); fputs(recvbuf,stdout); memset(sendbuf,0,sizeof(sendbuf)); memset(recvbuf,0,sizeof(recvbuf)); */ n = strlen(sendbuf.buf); sendbuf.len = htonl(n); written(sock,&sendbuf,4+n); int ret = readn(sock,&recvbuf.len,4); if(ret == -1) ERR_EXIT("read"); else if(ret < 4) { printf("peer close"); break; } n = ntohl(recvbuf.len); ret = readn(sock,recvbuf.buf,n); if(ret == -1) { ERR_EXIT("read"); } else if (ret < n) { printf("client close\n"); break; } fputs(recvbuf.buf,stdout); memset(&sendbuf,0,sizeof(sendbuf)); memset(&recvbuf,0,sizeof(recvbuf)); } close(sock); return 0; }

    推荐阅读