• 流协议与粘包


    • TCP:基于字节流的传输服务,无边界,不能保证对等方一次接受能能够返回好多字节
    • UDP:基于消息的传输服务,传输数据包有边界
    • 粘包产生的原因:
    • 粘包解决方案:
      • 定长包
      • 包尾加 (ftp)
      • 包头加上包体长度
      • 更复杂的应用层协议
    • readn writen(广域网必须处理粘包问题)
      • service
        •   1 #include <stdio.h>
            2 #include <errno.h>
            3 #include <string.h>
            4 #include <stdlib.h>
            5 #include <unistd.h>
            6 #include <sys/types.h>
            7 #include <sys/socket.h>
            8 #include <netinet/in.h>
            9 #include <arpa/inet.h>
           10 
           11 #define ERR_EXIT(m)
           12     do{
           13         perror(m);
           14         exit(EXIT_FAILURE);
           15     }while(0)
           16 
           17 struct packet
           18 {
           19     int len;
           20     char buf[1024];
           21 };
           22 
           23 ssize_t readn(int fd, void* buf,size_t count)
           24 {
           25     size_t nleft = count;
           26     ssize_t nread;
           27     char *bufp = (char*)buf;
           28     
           29     while(nleft > 0)
           30     {
           31         if((nread = read(fd,bufp,nleft)) < 0)
           32         {
           33             if(errno == EINTR)
           34                 continue;
           35             return -1;
           36         }
           37         else if(nread == 0)
           38         {
           39             return count-nleft;
           40         }
           41         
           42         bufp += nread;
           43         nleft -= nread;
           44     }
           45     return count;
           46 }
           47 
           48 ssize_t writen(int fd, void* buf,size_t count)
           49 {
           50     size_t nleft = count;
           51     ssize_t nwrite;
           52     char *bufp = (char*)buf;
           53     
           54     while(nleft > 0)
           55     {
           56         if((nwrite = write(fd,bufp,nleft)) < 0)
           57         {
           58             if (errno = EINTR)
           59                 continue;
           60             return -1;
           61         }
           62         else if(nwrite == 0)
           63             continue;
           64         bufp += nwrite;
           65         nleft -= nwrite;
           66     }    
           67     return count;
           68 }
           69 
           70 void do_service(int conn)
           71 {
           72 //    char recvbuf[1024];
           73     struct packet recvbuf;
           74     int n;
           75     while(1)
           76     {
           77         memset(&recvbuf,0,sizeof(recvbuf));
           78         int ret = readn(conn,&recvbuf.len,4);
           79         if(ret < 4)
           80         {
           81             printf("client close
          ");
           82             break;
           83         }
           84         else if(ret == -1)
           85             ERR_EXIT("read");
           86         n = ntohl(recvbuf.len);
           87         ret = readn(conn,&recvbuf.buf,n);
           88         if(ret == -1)
           89             ERR_EXIT("read");
           90         else if(ret < n)
           91         {
           92             printf("client close
          ");
           93             break;
           94         }
           95                 
           96         fputs(recvbuf.buf,stdout);
           97         writen(conn,&recvbuf,n+4);
           98     }
           99 }
          100 
          101 int main(void)
          102 {
          103     int listenfd;
          104     if((listenfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
          105         ERR_EXIT("socket");
          106 
          107     struct sockaddr_in servaddr;
          108     memset(&servaddr, 0, sizeof(servaddr));
          109     servaddr.sin_family = AF_INET;
          110     servaddr.sin_port = htons(5188);
          111     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
          112 
          113     int on;
          114     if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
          115         ERR_EXIT("setsockopt");
          116     if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
          117         ERR_EXIT("bind");
          118     if(listen(listenfd,SOMAXCONN) < 0)
          119         ERR_EXIT("listen");
          120     struct sockaddr_in peeraddr;
          121     socklen_t peerlen = sizeof(peeraddr);
          122     int conn;
          123 
          124     pid_t pid;
          125     while(1)
          126     {
          127         if((conn = accept(listenfd,(struct sockaddr*)&peeraddr,&peerlen)) < 0)
          128             ERR_EXIT("accept");
          129         printf("ip=%s,port=%d	
          ",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));
          130 
          131         pid = fork();
          132         if(pid == -1)
          133             ERR_EXIT("fork");
          134         if(pid == 0)
          135         {
          136             close(listenfd);
          137             do_service(conn);
          138             exit(EXIT_SUCCESS);
          139         }
          140         else
          141             close(conn);
          142     }
          143     return 0;    
          144 }
          View Code
      • client
        •   
            1 #include <stdio.h>
            2 #include <errno.h>
            3 #include <string.h>
            4 #include <stdlib.h>
            5 #include <unistd.h>
            6 #include <sys/types.h>
            7 #include <sys/socket.h>
            8 #include <netinet/in.h>
            9 #include <arpa/inet.h>
           10 
           11 #define ERR_EXIT(m)
           12     do{
           13         perror(m);
           14         exit(EXIT_FAILURE);
           15     }while(0)
           16 
           17 ssize_t readn(int fd, void* buf,size_t count)
           18 {
           19     size_t nleft = count;
           20     ssize_t nread;
           21     char *bufp = (char*)buf;
           22     
           23     while(nleft > 0)
           24     {
           25         if((nread = read(fd,bufp,nleft)) < 0)
           26         {
           27             if(errno == EINTR)
           28                 continue;
           29             return -1;
           30         }
           31         else if(nread == 0)
           32         {
           33             return count-nleft;
           34         }
           35         
           36         bufp += nread;
           37         nleft -= nread;
           38     }
           39     return count;
           40 }
           41 
           42 ssize_t writen(int fd, void* buf,size_t count)
           43 {
           44     size_t nleft = count;
           45     ssize_t nwrite;
           46     char *bufp = (char*)buf;
           47     
           48     while(nleft > 0)
           49     {
           50         if((nwrite = write(fd,bufp,nleft)) < 0)
           51         {
           52             if (errno = EINTR)
           53                 continue;
           54             return -1;
           55         }
           56         else if(nwrite == 0)
           57             continue;
           58         bufp += nwrite;
           59         nleft -= nwrite;
           60     }    
           61     return count;
           62 }
           63 
           64 void do_service(int conn)
           65 {
           66     char recvbuf[1024];
           67     while(1)
           68     {
           69         memset(recvbuf,0,sizeof(recvbuf));
           70         int ret = read(conn,recvbuf,sizeof(recvbuf));
           71         if(ret ==0)
           72         {
           73             printf("client close
          ");
           74             break;
           75         }
           76         else if(ret == -1)
           77             ERR_EXIT("read");
           78         fputs(recvbuf,stdout);
           79         write(conn,recvbuf,ret);
           80     }
           81 }
           82 
           83 struct packet
           84 {
           85     int len;
           86     char buf[1024];
           87 };
           88 
           89 int main(void)
           90 {
           91     int sock;
           92     if((sock= socket(AF_INET,SOCK_STREAM,0)) < 0)
           93         ERR_EXIT("socket");
           94 
           95     struct sockaddr_in servaddr;
           96     memset(&servaddr, 0, sizeof(servaddr));
           97     servaddr.sin_family = AF_INET;
           98     servaddr.sin_port = htons(5188);
           99     servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
          100 
          101     if(connect(sock,(struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
          102         ERR_EXIT("connect");
          103 
          104     struct packet sendbuf;
          105     struct packet recvbuf;
          106     memset(&sendbuf,0,sizeof(sendbuf));
          107     memset(&recvbuf,0,sizeof(recvbuf));
          108 
          109 //    char sendbuf[1024] = { 0 };
          110 //    char recvbuf[1024] = { 0 };
          111     int n;
          112     while(fgets(sendbuf.buf,sizeof(sendbuf.buf),stdin) != NULL)
          113     {
          114         n = strlen(sendbuf.buf);
          115         
          116         sendbuf.len =htonl(n);
          117         writen(sock,&sendbuf.len,4+n);
          118         //writen(sock,sendbuf,strlen(sendbuf));
          119         int ret = readn(sock,&recvbuf.len,4);
          120         if(ret == -1)
          121             ERR_EXIT("readn");
          122         else if(ret < 4)
          123         {
          124             printf("client close");
          125             break;
          126         }
          127         n = ntohl(sendbuf.len);
          128         ret = readn(sock,&recvbuf.buf,n);
          129         if(ret == -1)
          130             ERR_EXIT("readn");
          131         else if(ret < n)
          132         {
          133             printf("client close
          ");
          134             break;
          135         }
          136         
          137         fputs(recvbuf.buf,stdout);
          138 //        fputs(recvbuf,stdout);
          139 
          140         memset(&sendbuf,0, sizeof(sendbuf));
          141         memset(&recvbuf,0, sizeof(recvbuf));
          142     }
          143     close(sock);
          144     return 0;    
          145 }
          View Code
    作者:长风 Email:844064492@qq.com QQ群:607717453 Git:https://github.com/zhaohu19910409Dz 开源项目:https://github.com/OriginMEK/MEK 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 感谢您的阅读。如果觉得有用的就请各位大神高抬贵手“推荐一下”吧!你的精神支持是博主强大的写作动力。 如果觉得我的博客有意思,欢迎点击首页左上角的“+加关注”按钮关注我!
  • 相关阅读:
    Django 的简单ajax
    django 模板语言的注释操作
    Django 使用Paginator分页
    Django 使用allauth报错
    selenium登录 京东滑动验证码
    The usage of Markdown---表格
    The usage of Markdown---引用
    The usage of Markdown---代码块
    The usage of Markdown---目录
    The usage of Markdown---链接的使用
  • 原文地址:https://www.cnblogs.com/zhaohu/p/8962006.html
Copyright © 2020-2023  润新知