• 流协议与粘包(二)


    • read,write与recv,send
    • readline实现
    • 用readline实现回射客户、服务器
    • getsockname ,getpeername
    • gethostname,gethostbyname,gethostbyaddr
    1. 基于readline的回射客户/服务器
      1. 服务端
        1.   
            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 
           18 ssize_t readn(int fd, void* buf,size_t count)
           19 {
           20     size_t nleft = count;
           21     ssize_t nread;
           22     char *bufp = (char*)buf;
           23     
           24     while(nleft > 0)
           25     {
           26         if((nread = read(fd,bufp,nleft)) < 0)
           27         {
           28             if(errno == EINTR)
           29                 continue;
           30             return -1;
           31         }
           32         else if(nread == 0)
           33         {
           34             return count-nleft;
           35         }
           36         
           37         bufp += nread;
           38         nleft -= nread;
           39     }
           40     return count;
           41 }
           42 
           43 ssize_t writen(int fd, void* buf,size_t count)
           44 {
           45     size_t nleft = count;
           46     ssize_t nwrite;
           47     char *bufp = (char*)buf;
           48     
           49     while(nleft > 0)
           50     {
           51         if((nwrite = write(fd,bufp,nleft)) < 0)
           52         {
           53             if (errno = EINTR)
           54                 continue;
           55             return -1;
           56         }
           57         else if(nwrite == 0)
           58             continue;
           59         bufp += nwrite;
           60         nleft -= nwrite;
           61     }    
           62     return count;
           63 }
           64 
           65 ssize_t recv_peek(int fd, void* buf,size_t count)
           66 {
           67     while(1)
           68     {
           69         int ret = recv(fd,buf,count,MSG_PEEK);
           70         if(ret == -1 && errno == EINTR)
           71             continue;
           72         return ret;
           73     }
           74 }
           75 
           76 ssize_t readline(int sockfd,void *buf,size_t maxline)
           77 {
           78     int ret;
           79     int nread;
           80     char *bufp= buf;
           81     int nleft =maxline;
           82     while(1)
           83     {
           84         ret = recv_peek(sockfd,bufp,nleft);
           85         if(ret < 0)
           86             return ret;
           87         else if(ret == 0)
           88             return ret;
           89         nread = ret;
           90         int i;
           91         for(i = 0; i < nread; i++)
           92         {
           93             if(bufp[i] == '
          ')
           94             {
           95                 ret = readn(sockfd,bufp, i+1);
           96                 if(ret != i+1)
           97                     exit(EXIT_FAILURE);
           98                 return ret;
           99             }
          100         }
          101         if(nread > nleft)
          102             exit(EXIT_FAILURE);
          103         nleft -= nread;
          104         ret = readn(sockfd,bufp,nread);
          105         if(ret != nread)
          106             exit(EXIT_FAILURE);
          107         bufp += nread;
          108     } 
          109     return -1;
          110 }
          111 
          112 void do_service(int conn)
          113 {
          114     char recvbuf[1024];
          115     int n;
          116     while(1)
          117     {
          118         memset(recvbuf,0,sizeof(recvbuf));
          119         int ret = readline(conn,recvbuf,1024);
          120         if(ret == -1)
          121             ERR_EXIT("read");
          122         if(ret == 0)
          123         {
          124             printf("clien close");
          125             break;
          126         }
          127                 
          128         fputs(recvbuf,stdout);
          129         writen(conn,recvbuf,strlen(recvbuf));
          130     }
          131 }
          132 
          133 int main(void)
          134 {
          135     int listenfd;
          136     if((listenfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
          137         ERR_EXIT("socket");
          138 
          139     struct sockaddr_in servaddr;
          140     memset(&servaddr, 0, sizeof(servaddr));
          141     servaddr.sin_family = AF_INET;
          142     servaddr.sin_port = htons(5188);
          143     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
          144 
          145     int on;
          146     if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
          147         ERR_EXIT("setsockopt");
          148     if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
          149         ERR_EXIT("bind");
          150     if(listen(listenfd,SOMAXCONN) < 0)
          151         ERR_EXIT("listen");
          152     struct sockaddr_in peeraddr;
          153     socklen_t peerlen = sizeof(peeraddr);
          154     int conn;
          155 
          156     pid_t pid;
          157     while(1)
          158     {
          159         if((conn = accept(listenfd,(struct sockaddr*)&peeraddr,&peerlen)) < 0)
          160             ERR_EXIT("accept");
          161         printf("ip=%s,port=%d	
          ",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));
          162 
          163         pid = fork();
          164         if(pid == -1)
          165             ERR_EXIT("fork");
          166         if(pid == 0)
          167         {
          168             close(listenfd);
          169             do_service(conn);
          170             exit(EXIT_SUCCESS);
          171         }
          172         else
          173             close(conn);
          174     }
          175     return 0;    
          176 }
          View Code
      2. 客户端
        1.   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 size_t recv_peek(int fd, void* buf,size_t count)
           65 {
           66         while(1)
           67         {
           68                 int ret = recv(fd,buf,count,MSG_PEEK);
           69                 if(ret == -1 && errno == EINTR)
           70                         continue;
           71                 return ret;
           72         }
           73 }
           74 
           75 ssize_t readline(int sockfd,void *buf,size_t maxline)
           76 {
           77         int ret;
           78         int nread;
           79         char *bufp= buf;
           80         int nleft =maxline;
           81         while(1)
           82         {
           83                 ret = recv_peek(sockfd,bufp,nleft);
           84                 if(ret < 0)
           85                         return ret;
           86                 else if(ret == 0)
           87                         return ret;
           88                 nread = ret;
           89                 int i;
           90                 for(i = 0; i < nread; i++)
           91                 {
           92                         if(bufp[i] == '
          ')
           93                         {   
           94                                 ret = readn(sockfd,bufp, i+1);
           95                                 if(ret != i+1)
           96                                         exit(EXIT_FAILURE);
           97                                 return ret;
           98                         }
           99                 }   
          100                 if(nread > nleft)
          101                         exit(EXIT_FAILURE);
          102                 nleft -= nread;
          103                 ret = readn(sockfd,bufp,nread);
          104                 if(ret != nread)
          105                         exit(EXIT_FAILURE);
          106                 bufp += nread;
          107         }
          108         return -1; 
          109 }
          110 
          111 int main(void)
          112 {
          113     int sock;
          114     if((sock= socket(AF_INET,SOCK_STREAM,0)) < 0)
          115         ERR_EXIT("socket");
          116 
          117     struct sockaddr_in servaddr;
          118     memset(&servaddr, 0, sizeof(servaddr));
          119     servaddr.sin_family = AF_INET;
          120     servaddr.sin_port = htons(5188);
          121     servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
          122 
          123     if(connect(sock,(struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
          124         ERR_EXIT("connect");
          125 
          126     struct sockaddr_in localaddr;
          127     socklen_t addrlen = sizeof(localaddr);
          128     if(getsockname(sock,(struct sockaddr*)&localaddr,&addrlen) < 0)
          129         ERR_EXIT("getsockname");
          130     printf("ip=%s,port=%d	
          ",inet_ntoa(localaddr.sin_addr),ntohs(localaddr.sin_port));
          131     char sendbuf[1024] = { 0 };
          132     char recvbuf[1024] = { 0 };
          133     int n;
          134     while(fgets(sendbuf,sizeof(sendbuf),stdin) != NULL)
          135     {
          136         writen(sock,sendbuf,strlen(sendbuf));
          137         int ret = readline(sock,recvbuf,sizeof(sendbuf));
          138         if(ret == -1)
          139             ERR_EXIT("readn");
          140         else if(ret ==  0)
          141         {
          142             printf("client close");
          143             break;
          144         }
          145         
          146         fputs(recvbuf,stdout);
          147 //        fputs(recvbuf,stdout);
          148 
          149         memset(sendbuf,0, sizeof(sendbuf));
          150         memset(recvbuf,0, sizeof(recvbuf));
          151     }
          152     close(sock);
          153     return 0;    
          154 }
          View Code
    2. gethostname

        

     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 #include <netdb.h>
    11 
    12 #define ERR_EXIT(m)
    13     do{
    14         perror(m);
    15         exit(EXIT_FAILURE);
    16     }while(0)
    17 
    18 int getlocalip(char *ip)
    19 {
    20     char host[100] = { 0 };
    21     if(gethostname(host,sizeof(host)) < 0)
    22         return -1;
    23 
    24     struct hostent *hp;
    25         if((hp = gethostbyname(host)) == NULL)
    26         return -1;
    27 
    28     strcpy(ip,inet_ntoa(*(struct in_addr*)hp->h_addr_list[0]));
    29     return 0;
    30 }
    31 
    32 int main()
    33 {
    34     char host[100] = { 0 };
    35     if(gethostname(host,sizeof(host)) < 0)
    36         ERR_EXIT("gethostname");
    37     
    38     struct hostent *hp;
    39     if((hp = gethostbyname(host)) == NULL)
    40         ERR_EXIT("gethostbyname");
    41     
    42     int i = 0;
    43     while(hp->h_addr_list[i] != NULL)
    44     {
    45         printf("%s
    ",inet_ntoa(*(struct in_addr*)hp->h_addr_list[i]));
    46         i++;
    47     }
    48     char ip[16] = { 0 };
    49     getlocalip(ip);
    50     printf("localip=%s
    ",ip);
    51     return 0;
    52 }
    View Code
    作者:长风 Email:844064492@qq.com QQ群:607717453 Git:https://github.com/zhaohu19910409Dz 开源项目:https://github.com/OriginMEK/MEK 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 感谢您的阅读。如果觉得有用的就请各位大神高抬贵手“推荐一下”吧!你的精神支持是博主强大的写作动力。 如果觉得我的博客有意思,欢迎点击首页左上角的“+加关注”按钮关注我!
  • 相关阅读:
    三调数据库标注插件
    ionic ios 打包发布流程
    ionic ios 打包 真机测试常见问题
    使用Jquery Viewer 展示图片信息
    微信支付退款证书服务器配置
    帝国CMS站点迁移
    solr 服务器搭建(Linux版)
    ionic ios 打包
    Solr 同义词搜索
    ionic 环境搭建
  • 原文地址:https://www.cnblogs.com/zhaohu/p/8963174.html
Copyright © 2020-2023  润新知