socket编程中的粘包问题解决方案

1.自定义传输,数据结构。struct packet.

服务器端:

  1 #include <unistd.h>
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <sys/socket.h>
  5 #include <sys/types.h>
  6 #include <errno.h>
  7 #include <arpa/inet.h>
  8 #include <netinet/in.h>
  9 #include <string.h>
 10 
 11 
 12 // allow multi client to connect .
 13 
 14 #define ERR_EXIT(m) \
 15         do { \
 16             perror(m); \
 17             exit(EXIT_FAILURE); \
 18         } while(0) 
 19 
 20 struct packet
 21 {
 22     int len;
 23     char buf[1024];
 24 };
 25 
 26 ssize_t readn(int fd, void* buf, size_t count)
 27 {
 28     size_t nleft = count;
 29     size_t nread;
 30     char  *pbuf = (char*)buf;
 31     
 32     printf("nread\n");
 33     while(nleft > 0)
 34     {
 35         printf("nleft:%d\n", nleft);
 36         if((nread = read(fd, pbuf, nleft)) < 0)
 37         {
 38 
 39             if(errno == EINTR)
 40                 continue;
 41 
 42             return -1;
 43         }
 44         else if (nread == 0)
 45             return count - nleft;
 46 
 47         printf("nread:%d\n", nread);
 48 
 49         pbuf += nread;
 50         nleft -= nread;
 51     }
 52 
 53     return count;
 54 }
 55 
 56 ssize_t writen(int fd, const void *buf, size_t count)
 57 {
 58 
 59     size_t nleft = count;
 60     size_t nwriten;
 61     char  *pbuf = (char*)buf;
 62 
 63     while(nleft > 0)
 64     {
 65         if((nwriten = write(fd, pbuf, nleft)) < 0)
 66         {
 67             if(errno == EINTR)
 68                 continue;
 69 
 70             return -1;
 71         }
 72         else if (nwriten == 0)
 73             continue;
 74 
 75         pbuf += nwriten;
 76         nleft -= nwriten;
 77     }
 78 
 79     return count;
 80 
 81 }
 82 
 83 void do_service(int connfd)
 84 {
 85     //char recvbuf[1024];
 86     struct packet recvbuf;
 87     int n;
 88     while(1)
 89     {
 90         memset(&recvbuf, 0, sizeof(recvbuf));
 91         int ret = readn(connfd, &recvbuf.len, 4); // 4 = sizeof(sendbuf.len)
 92 
 93         if(ret == -1)
 94         {
 95             ERR_EXIT("read error!\n");
 96         }
 97         else if(ret == 4) // 
 98         {
 99             printf("client close\n");
100             break;
101         }
102         
103         n = ntohl(recvbuf.len);//convert network order to host
104         ret = readn(connfd, &recvbuf.buf, n); // 4 = sizeof(sendbuf.len)
105 
106         if(ret == -1)
107         {
108             ERR_EXIT("read error!\n");
109         }
110         else if(ret == 4) // 
111         {
112             printf("client close\n");
113             break;
114         }
115         fputs(recvbuf.buf, stdout);
116         writen(connfd, &recvbuf, 4+n);
117     }
118     close(connfd);
119 }
120 
121 int main(int argc, char* argv[])
122 {
123     int listenfd ;
124     if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
125     {
126         ERR_EXIT("socket");
127     }
128 
129     struct sockaddr_in   servaddr;
130     memset(&servaddr, 0, sizeof(servaddr));
131     servaddr.sin_family = AF_INET;
132     servaddr.sin_port = htons(5188);
133     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
134     // servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
135     // inet_aton("127.0.0.1", &servaddr.sin_addr);
136 
137     // add begin
138     int on = 1;//open  TIME_WAIT status allow the server to restart
139     if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
140     {
141         ERR_EXIT("setsockopt");
142     }
143     // add end
144 
145     if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
146     {
147         ERR_EXIT("bind");
148     }
149 
150     if(listen(listenfd, SOMAXCONN) < 0)
151     {
152         ERR_EXIT("listen");
153     }
154 
155     struct sockaddr_in peeraddr;
156     socklen_t  peerlen = sizeof(peeraddr);
157     
158     int connfd ;
159 
160 
161     pid_t pid;
162 
163     while(1)
164     {
165         if((connfd = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0)
166         {
167             ERR_EXIT("accept");
168         }
169 
170         printf("IP:%s, Port:%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));
171 
172         pid = fork();
173         if(pid == -1) 
174             ERR_EXIT("fork");
175 
176         if(pid == 0) // child process 
177         {
178 
179             close(listenfd);
180             do_service(connfd);
181             exit(EXIT_SUCCESS);//while client close, processor need be exited
182         }
183         else // accept
184         { 
185             close(connfd); // needn't deal connfd
186         }
187     }
188 
189     return 0;
190 }


客户端:

  1 #include <unistd.h>
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <errno.h>
  5 #include <string.h>
  6 
  7 #include <sys/socket.h>
  8 #include <arpa/inet.h>
  9 #include <sys/types.h>
 10 #include <netinet/in.h>
 11 
 12 #define ERR_EXIT(m) \
 13         do { \
 14             perror(m); \
 15             exit(EXIT_FAILURE); \
 16         } while(0) 
 17 
 18 struct packet
 19 {
 20     int len;
 21     char buf[1024];
 22 };
 23 
 24 ssize_t readn(int fd, void* buf, size_t count)
 25 {
 26     size_t nleft = count;
 27     size_t nread;
 28     char  *pbuf = (char*)buf;
 29 
 30     while(nleft > 0)
 31     {
 32         if((nread = read(fd, pbuf, nleft)) < 0)
 33         {
 34             if(errno == EINTR)
 35                 continue;
 36 
 37             return -1;
 38         }
 39         else if (nread == 0)
 40             return count - nleft;
 41 
 42         pbuf += nread;
 43         nleft -= nread;
 44     }
 45 
 46     return count;
 47 }
 48 
 49 ssize_t writen(int fd, const void *buf, size_t count)
 50 {
 51 
 52     size_t nleft = count;
 53     size_t nwriten;
 54     char  *pbuf = (char*)buf;
 55 
 56     while(nleft > 0)
 57     {
 58         if((nwriten = write(fd, pbuf, nleft)) < 0)
 59         {
 60             if(errno == EINTR)
 61                 continue;
 62 
 63             return -1;
 64         }
 65         else if (nwriten == 0)
 66             continue;
 67 
 68         pbuf += nwriten;
 69         nleft -= nwriten;
 70     }
 71 
 72     return count;
 73 
 74 }
 75 
 76 int main(int argc, char* argv[])
 77 {
 78     int sockfd;
 79     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
 80     {
 81         ERR_EXIT("socket");
 82     }
 83 
 84     struct sockaddr_in addr;
 85     addr.sin_family = AF_INET;
 86     addr.sin_port   = htons(5188);
 87     addr.sin_addr.s_addr = inet_addr("127.0.0.1");
 88 
 89     if(connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
 90     {
 91         ERR_EXIT("connect");
 92     }
 93 
 94     struct packet sendbuf;
 95     struct packet recvbuf;
 96     memset(&sendbuf, 0, sizeof(sendbuf));
 97     memset(&recvbuf, 0, sizeof(recvbuf));
 98     
 99     int n;
100     while(fgets(&sendbuf.buf, sizeof(sendbuf.len), stdin) != NULL)
101     {
102         n = strlen(sendbuf.buf);
103         sendbuf.len = htonl(n);//convert the data to network order
104         writen(sockfd, &sendbuf, 4 + n);// n represents sizeof(sendbuf.len);
105 
106         int ret = readn(sockfd, &recvbuf.len, 4); // 4 = sizeof(sendbuf.len)
107 
108         if(ret == -1)
109         {
110             ERR_EXIT("read error!\n");
111         }
112         else if(ret == 4) // 
113         {
114             printf("client close\n");
115             break;
116         }
117         
118         n = ntohl(sendbuf.len);//convert network order to host
119         ret = readn(sockfd, &recvbuf.buf, n); // 4 = sizeof(sendbuf.len)
120 
121         if(ret == -1)
122         {
123             ERR_EXIT("read error!\n");
124         }
125         else if(ret == 4) // 
126         {
127             printf("client close\n");
128             break;
129         }
130         fputs(recvbuf.buf, stdout);
131         memset(&recvbuf, 0, sizeof(recvbuf));
132         memset(&sendbuf, 0, sizeof(sendbuf));
133     }
134 
135     close(sockfd);
136     return 0;
137 }

 

自定数据包在socket编程中传递。

posted on 2017-12-09 23:35  【呵呵V嘿嘿】  阅读(613)  评论(0编辑  收藏  举报

导航