免费注册 查看新帖 |

Chinaunix

广告
  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4104 | 回复: 3
打印 上一主题 下一主题

网络编程,单线程select,客户端连接几次后,服务器就不返回数据 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-05-20 19:04 |只看该作者 |倒序浏览
本帖最后由 setsuna 于 2010-05-20 19:20 编辑

server端运行在linux下,使用单线程+ select多路复用模型。client运行在win下。client发送命令来通知server,server返回数据给client。
遇到的问题: 比如server端listen的backlog为5,那么client在连接4次之后就会出现:可以连接server,但是客户端发送数据给server,server端select总是返回0并且不会返回数据给client。
请问是代码哪里出了错?万分感谢!
代码大致如下:
  1.     //创建侦听Socket
  2.     if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  3.     {
  4.         perror("Create listening socket error!");
  5.         exit(1);
  6.     }
  7.    
  8.         int flags;
  9.         if(flags= fcntl(sock_fd, F_GETFL, 0) <0)
  10.         {
  11.                 printf("F_GETFL errors, %s\n", strerror(errno));
  12.                 return -1;
  13.         }
  14.         flags |= O_NONBLOCK;
  15.         if(flags= fcntl(sock_fd, F_SETFL, 0) <0)
  16.         {
  17.                 printf("F_SETFL O_NONBLOCK errors, %s\n", strerror(errno));
  18.                 return -1;
  19.         }
  20.         //配置侦听Socket
  21.     //SO_REUSEADDR BOOL 允许套接口和一个已在使用中的地址捆绑。
  22.     if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
  23.     {
  24.         perror("setsockopt error!");
  25.         exit(1);
  26.     }
  27.    
  28.     server_addr.sin_family = AF_INET;         // host byte order
  29.     server_addr.sin_port = htons(MYPORT);     // short, network byte order
  30.     server_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
  31.     memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));

  32.     //绑定新创建的Socket到指定的IP和端口
  33.     if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
  34.     {
  35.         perror("bind error!");
  36.         exit(1);
  37.     }
  38.     //开始侦听,最大连接数为BACKLOG
  39.     if (listen(sock_fd, BACKLOG) == -1)
  40.     {
  41.         perror("listen error!");
  42.         exit(1);
  43.     }
  44.    
  45.     //监控文件描述符集合
  46.     fd_set fdsr;
  47.     //监控文件描述符集合中最大的文件号
  48.     int maxsock;
  49.     //Select超时返回的时间。
  50.     struct timeval  tv;

  51.     conn_amount = 0;
  52.     sin_size = sizeof(client_addr);
  53.     maxsock = sock_fd;
  54.         for(i = 0; i< BACKLOG; i++)
  55.         {
  56.                 fd_A[i] = -1;
  57.         }
  58.         // 初始化文件描述符集合 initialize file descriptor set
  59.         FD_ZERO(&fdsr);
  60.         // 把Sock_fd加入到文件描述符集合
  61.         FD_SET(sock_fd, &fdsr);

  62.     while (1)
  63.     {

  64.         // 超时设置30秒
  65.         tv.tv_sec = 30;
  66.         tv.tv_usec = 0;

  67.         int nready = select(maxsock + 1, &fdsr, NULL, NULL, &tv);

  68.         if (nready < 0)
  69.         {
  70.             perror("select error!");
  71.             break;
  72.         }
  73.         else if (nready == 0)
  74.         {
  75.             printf("timeout\n");
  76.             continue;
  77.         }
  78.                 // 检查是否有新连接进来,如果有新连接进来,接收连接,生成新socket,

  79.         //并加入到监控文件描述符集合中。
  80.         if (FD_ISSET(sock_fd, &fdsr))
  81.         {
  82.             //接受连接
  83.             new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
  84.             if (new_fd <= 0)
  85.             {
  86.                 perror("accept socket error!");
  87.                 continue;
  88.             }
  89.             for (i = 0; i < BACKLOG; i++)
  90.             {
  91.                         if(fd_A[i] < 0)
  92.                         {
  93.                                 fd_A[i] = new_fd;
  94.                                 printf("new connection client[%d] %s:%d\n", conn_amount,inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
  95.                                 break;
  96.                         }

  97.             }
  98.                 if(i == BACKLOG)
  99.                 {
  100.                         printf("too many clients: %d\n", i);
  101.                         exit(0);
  102.                 }
  103.                 FD_SET(new_fd, &fdsr);
  104.                 if(new_fd > maxsock)
  105.                         maxsock = new_fd;
  106.                 if(maxi <i)
  107.                         maxi = i;
  108.                 if(--nready <= 0)
  109.                         continue;
  110.         }
  111.                 int tmp_sock;
  112.         // 轮询各个文件描述符(socket)
  113.         for (i = 0; i <= maxi; i++)
  114.         {
  115.              //FD_ISSET(int fd, fdset *fdset):检查fdset联系的文件句柄fd是否可读写,
  116.                          printf("start\n");
  117.                         if((tmp_sock = fd_A[i]) <0)
  118.                                 continue;
  119.              // >0表示可读写。
  120.             if (FD_ISSET(tmp_sock, &fdsr))
  121.             {
  122.                 // 接收数据
  123.                 ret = recv(fd_A[i], buf, sizeof(buf), 0);
  124.                 if (ret <= 0) //接收数据出错
  125.                 {      
  126.                     printf("client[%d] close\n", i);
  127.                     close(fd_A[i]);
  128.                     FD_CLR(fd_A[i], &fdsr);
  129.                     fd_A[i] = -1;
  130.                 }
  131.                 else  // 数据接收成功
  132.                 {
  133.                         //返回数据,暂略!
  134.                 }
  135.                  if(--nready <= 0)
  136.                         continue;
  137.             }
  138.         }
  139.     }
复制代码

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
2 [报告]
发表于 2010-05-20 19:14 |只看该作者
每次select之前fdsr要重新准备

论坛徽章:
0
3 [报告]
发表于 2010-05-20 19:26 |只看该作者
每次select之前fdsr要重新准备
hellioncu 发表于 2010-05-20 19:14


成功了!非常感谢!非常感谢!

论坛徽章:
0
4 [报告]
发表于 2010-05-20 20:38 |只看该作者
经常犯得错误。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP