• tcp/ip通信第5期之客户机端程序


      1 /*此程序是tcp/ip通信的客户机端程序,
      2   测试运行在redhat6系统上
      3   重构readline函数,解决粘包问题——利用“
    ”识别一个消息边界
      4 */
      5 #include<stdio.h>
      6 #include<stdlib.h>
      7 #include<unistd.h>
      8 #include<sys/types.h>
      9 #include<sys/socket.h>
     10 #include<arpa/inet.h>
     11 #include<netinet/in.h>
     12 #include<string.h>
     13 #include<signal.h>
     14 #include<errno.h>
     15 
     16 #define port 5188
     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     while (nleft > 0)
     24             {
     25                 if ((nread = read(fd, bufp, nleft)) < 0)
     26                 {
     27                     if (errno == EINTR)
     28  //被信号中断,errno这个全局变量的值就会等于EINTR。
     29                         continue;
     30                     return -1;
     31                 }
     32                 else if (nread == 0) //对方关闭或者已经读到eof
     33                     return count - nleft;
     34                 bufp += nread;
     35                 nleft -= nread;
     36             }
     37             return count;
     38 }
     39      
     40 ssize_t writen(int fd, const void * buf, size_t count) 
     41 {
     42         size_t nleft = count;
     43         ssize_t nwritten;
     44         char *bufp = (char *)buf;
     45         while (nleft > 0)
     46             {
     47                 if ((nwritten = write(fd, bufp, nleft)) < 0)
     48                 {
     49                     if (errno == EINTR)
     50                         continue;
     51  //要保证读取的字节数为指定字节数,所以继续
     52                     return -1;
     53                 }
     54                 else if (nwritten == 0)        
     55                     continue;
     56  //由于其他原因引起的什么都没有写进,则继续操作,保证指定字节数
     57                 bufp += nwritten;
     58                 nleft -= nwritten;
     59             }
     60             return count;
     61 }
     62 
     63 ssize_t recv_peek(int sockfd,void *buf,size_t len)
     64 {
     65     while(1)
     66     {
     67         int ret=recv(sockfd,buf,len,MSG_PEEK);
     68         if(ret==-1&&errno==EINTR)
     69             continue;
     70         return ret;
     71     }
     72 }
     73 
     74 ssize_t recv_line(int sockfd,void *buf,size_t len)
     75 {
     76     int ret;//记录函数返回值
     77     int nread;//已经读到的字节数
     78     char *bufp=buf;
     79     int nleft=len;
     80     while(1)
     81     {
     82         ret=recv_peek(sockfd,bufp,nleft);
     83         if(ret<0)
     84             return ret;
     85         else if(ret==0)
     86             return ret;
     87         nread=ret;
     88         int i;
     89         for(i=0;i<nread;i++)
     90         {
     91             if(bufp[i]=='
    ')
     92             {
     93                 ret=readn(sockfd,bufp,i+1);
     94                 if(ret!=i+1)
     95                     exit(1);
     96                 return ret;
     97             }
     98         }
     99         if(nread>nleft)
    100             exit(1);
    101         nleft -= nread;
    102         ret=readn(sockfd,bufp,nread);
    103         if(ret!=nread)
    104             exit(0);
    105         bufp+=nread;
    106     }
    107     return -1;
    108 }
    109 
    110 int main()
    111 {
    112     int sock;
    113     //*****创建套接字*******
    114     if((sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
    115     /*if((listenfd=socket(PF_INET,SOCK_STREAM,0))<0)*/
    116         perror("error");
    117         
    118     //*******ipv4地址结构**********
    119     struct sockaddr_in servaddr;
    120     memset(&servaddr,0,sizeof(servaddr)); //清空结构体变量
    121     servaddr.sin_family=AF_INET;
    122     servaddr.sin_port= htons(port); //使用端口号:5188
    123     servaddr.sin_addr.s_addr=inet_addr("192.168.248.129");  //ip地址使用对方的地址,即服务器地址
    124     printf("the port_id:%d
    ",port);
    125     
    126     //*********连接请求************
    127     if(connect(sock,(struct sockaddr*)(&servaddr),sizeof(servaddr))<0)  //使用对方的ip地址
    128         perror("error");
    129     else
    130         printf("connected success.
    ");
    131     
    132     //************通信过程*************
    133     char sendbuf[1024]={0};
    134     char recvbuf[1024]={0};
    135     while(fgets(sendbuf,sizeof(sendbuf),stdin)!=NULL)
    136     {
    137         writen(sock,sendbuf,strlen(sendbuf));
    138         int ret=recv_line(sock,recvbuf,sizeof(recvbuf));
    139         if(ret==-1)
    140             perror("error
    ");
    141         if(ret==0)
    142         {
    143             printf("peer is closed.
    ");
    144             break;
    145         }
    146         
    147         fputs(recvbuf,stdout);
    148         memset(sendbuf,0,sizeof(sendbuf)); //清空缓存
    149         memset(recvbuf,0,sizeof(recvbuf));
    150     }
    151     close(sock);
    152     return 0;
    153 }
    内在的趣味,表面的繁琐
  • 相关阅读:
    Python安装appium 遇见的报错
    appium
    QQ邮箱/微信邮箱发送邮件
    Python-变量
    神秘的咒语
    宿命的PSS
    E. Congruence Equation
    D. Substring
    leetcode 761. Special Binary String
    F
  • 原文地址:https://www.cnblogs.com/data1213/p/4815856.html
Copyright © 2020-2023  润新知