• 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
    ");
     33     while(nleft > 0)
     34     {
     35         printf("nleft:%d
    ", 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
    ", 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!
    ");
     96         }
     97         else if(ret == 4) // 
     98         {
     99             printf("client close
    ");
    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!
    ");
    109         }
    110         else if(ret == 4) // 
    111         {
    112             printf("client close
    ");
    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
    ", 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!
    ");
    111         }
    112         else if(ret == 4) // 
    113         {
    114             printf("client close
    ");
    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!
    ");
    124         }
    125         else if(ret == 4) // 
    126         {
    127             printf("client close
    ");
    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编程中传递。

  • 相关阅读:
    使网页变灰的代码(包括FLASH等所有网页元素).
    技术面试问题回答
    Spring总结
    IE9插件差不多完成了
    通过dymamic简化Pinvoke调用
    shuffle算法的一种简易实现
    用Reactive Extensions快速实现鼠标手势功能
    编写递归调用的Lambda表达式
    Visual Studio 11 开发者预览版可以下载了
    关于获取所有排列方式的算法
  • 原文地址:https://www.cnblogs.com/liuxw7/p/8013165.html
Copyright © 2020-2023  润新知