Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2150453
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2015-06-17 14:53:46

1. 异常描述
1.1
a. client 连接到server之后,server fork一个child,正常通信
b. 将client的输入重定向
    cat client.c | ./client > t
      client--->一直发送数据并等侍应答-->当最后一个数据发送完成后-->关闭读写通道
      server--->当client关闭读写通道时,由于网络有延迟&&应答确认
                    -->导致通道的数据没有来得及发送到client端就被丢弃了
c. 解决方法用shutdown来关闭
1.2 缓冲机制
    这个还没有看明白,为什么fgets会导致丢数据,有弄明白的大神,让我好好请教一下!!


2.client.c
  1. cong@msi:/work/test/tcpip/11select/client$ cat client.c
  2. #include "utils.h"

  3. //#define TIME_SERV_ADDR "192.168.4.98"
  4. #define TIME_SERV_ADDR "127.0.0.1"

  5. ssize_t readline(int fd, void* vptr, size_t maxlen)
  6. {
  7.     ssize_t n, rc;
  8.     char c,*ptr;
  9.     ptr = vptr;
  10.     for(n=0; n<maxlen; n++)
  11.     {
  12. again:
  13.         if( (rc=read(fd,&c,1)) == 1)
  14.         {
  15.             *ptr++ = c;
  16.             if(c == '\n')
  17.                 break;
  18.         } else if(rc == 0) {
  19.             *ptr = 0;
  20.             return n;
  21.         }else {
  22.             if( errno == EINTR)
  23.                 goto again;
  24.             return -1;
  25.         }
  26.     }
  27.     *ptr = '\0';
  28.     return n;
  29. }

  30. #if 0   //原始版
  31. void str_cli(FILE* fp, int sockfd)
  32. {
  33.     char sendline[MAXLINE], recvline[MAXLINE];
  34.     while(fgets(sendline, MAXLINE, fp) != NULL)
  35.     {
  36.         write(sockfd, sendline, strlen(sendline));

  37.         if(readline(sockfd, recvline, MAXLINE) == 0)
  38.             dbmsg("server terminated");
  39.         fputs(recvline, stdout);
  40.     }

  41. }
  42. #endif
  43. #if 1   //第1次改动
  44. void str_cli(FILE* fp, int sockfd)
  45. {
  46.     int maxfdp1,ret, stdineof;
  47.     fd_set rset;
  48.     char sendline[MAXLINE], recvline[MAXLINE];
  49.     FD_ZERO(&rset);
  50.     while(1)
  51.     {
  52.         if(stdineof == 0)           //2.3当发送完成后,标志位=1,也就不把写端加入到select队列中了
  53.             FD_SET(fileno(fp), &rset);
  54.         FD_SET(sockfd, &rset);
  55.         maxfdp1 = max(fileno(fp), sockfd)+1;
  56.         //dbmsg("fd=%d,sockfd=%d,maxfdp1=%d",fileno(fp), sockfd, maxfdp1);
  57.         ret = select(maxfdp1, &rset, NULL, NULL, NULL);
  58.         if(ret <= 0)
  59.             continue;
  60.         if(FD_ISSET(sockfd, &rset))
  61.         {
  62.             if( (readline(sockfd, recvline, MAXLINE)) == 0)
  63.             {
  64.                 if(stdineof == 1)
  65.                     return ;
  66.                 else
  67.                     dbmsg("server terminated");
  68.             }
  69.             fputs(recvline, stdout);
  70.         }
  71.         if(FD_ISSET(fileno(fp),&rset))
  72.         {
  73.             if(fgets(sendline, MAXLINE, fp) == NULL)
  74.             {
  75.                 stdineof = 1;               //2.1当发送完成后,置位标志位
  76.                 shutdown(sockfd, SHUT_WR)//2.2当发送完成后,关闭write端
  77.                 FD_CLR(fileno(fp), &rset)//2.3当发送完成后,将写的fd从select队列中剔除
  78.                 continue;
  79.             }
  80.             write(sockfd, sendline, strlen(sendline));
  81.         }
  82.     }
  83. }
  84. #endif

  85. #if 0   //第2次改动
  86. void str_cli(FILE* fp, int sockfd)
  87. {
  88.     int maxfdp1,ret;
  89.     int stdineof = 0;
  90.     fd_set rset;
  91.     //char sendline[MAXLINE], recvline[MAXLINE];
  92.     char buf[MAXLINE];
  93.     int n;
  94.     FD_ZERO(&rset);
  95.     while(1)
  96.     {
  97.         if(stdineof == 0)
  98.             FD_SET(fileno(fp), &rset);
  99.         FD_SET(sockfd, &rset);
  100.         maxfdp1 = max(fileno(fp), sockfd)+1;
  101.         //dbmsg("fd=%d,sockfd=%d,maxfdp1=%d",fileno(fp), sockfd, maxfdp1);
  102.         ret = select(maxfdp1, &rset, NULL, NULL, NULL);
  103.         if(ret <= 0)
  104.             continue;
  105.         if(FD_ISSET(sockfd, &rset))
  106.         {
  107.             //if( (readline(sockfd, recvline, MAXLINE)) == 0)
  108.             if( (n=read(sockfd, buf, MAXLINE)) == 0)
  109.             {
  110.                 if(stdineof == 1)
  111.                     return ;
  112.                 else
  113.                     dbmsg("server terminated");
  114.             }
  115.             write(fileno(stdout),buf, n);
  116.         }
  117.         if(FD_ISSET(fileno(fp),&rset))
  118.         {
  119.             //if(fgets(sendline, MAXLINE, fp) == NULL)
  120.             if( (n=read(fileno(fp), buf, MAXLINE)) == 0)
  121.             {
  122.                 stdineof = 1;
  123.                 shutdown(sockfd, SHUT_WR);
  124.                 FD_CLR(fileno(fp), &rset);
  125.                 continue;
  126.             }
  127.             //write(sockfd, sendline, strlen(sendline));
  128.             write(sockfd, buf, n);
  129.         }
  130.     }
  131. }
  132. #endif

  133. int main ( int argc, char *argv[] )
  134. {
  135.     int i;
  136.     int sockfd, n;
  137.     struct sockaddr_in servaddr;
  138.     char recvline[1024];
  139.     sockfd = socket(AF_INET, SOCK_STREAM, 0);
  140.     if(sockfd < 0)
  141.         return -1;
  142.     bzero(&servaddr, sizeof(servaddr));
  143.     servaddr.sin_family = AF_INET;
  144.     servaddr.sin_port = htons(13999);
  145.     inet_pton(AF_INET, TIME_SERV_ADDR, &servaddr.sin_addr);
  146.     if( connect(sockfd, (const struct sockaddr*)&servaddr, sizeof(servaddr))< 0)
  147.         return -1;
  148.     dbmsg("connect success");
  149.     str_cli(stdin, sockfd);
  150.     return EXIT_SUCCESS;
  151. }

client.rar (下载后改名为client.tar.gz)
serv.rar  (下载后改名为serv.tar.gz)
阅读(1064) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~