select低级错误

来源:互联网 发布:企业淘宝开店流程 编辑:程序博客网 时间:2024/05/22 01:50

本来不想吐槽的了,但是想到会有很多初学者犯了我所犯过的低级错误,找bug找了一天都找不到,还是决定写写这个比较隐性的错误把。(ps:本人菜鸟一枚)

如下典型的select多路复用套接口代码

fd_set         rset;  int             socket_one, socket_two, maxfd;  /*  一些列的初始化代码 */    maxfd = socket_one > socket_two ? socket_one: socket_two;    FD_ZERO(&rset);  FD_SET(socket_one, &rset);  FD_SET(socket_two, &rset);    while(1){      select(maxfd + 1, &rset, NULL, NULL, NULL);      if(FD_ISSET(socket_one, &rset)){          /* 代码*/      }            if(FD_ISSET(socket_two, &rset)){          /*代码*/      }  }  
一眼看上去似乎没有么多大的问题,但是把程序编译跑起来之后(假如你预计select第一次返回,socket_one可读,select第二次返回socket_two可读),情况并不如你所想。第二次当socket_two可读的时候,程序根本就不去读socket_two套接口!
出现这个隐性bug的原因在于select第一次返回的时候,只有socket_two在rset集合里面。因此当程序再次select的时候,相当于  

FD_ZERO(&rset);  FD_SET(socket_one, &rset);  select(maxfd + 1, &rset, NULL, NULL, NULL);
也就是说第二次的select只是检测socket_one是否可读,socket_two是否可读已经不能检测到!正确的代码应该如下:

fd_set          rset, allset;/*添加一个allset的变量,存储所有想要检查的套接口*/  int             socket_one, socket_two, maxfd;  /*  一些列的初始化代码 */    maxfd = socket_one > socket_two ? socket_one: socket_two;    FD_ZERO(&allset);  FD_SET(socket_one, &allset);  FD_SET(socket_two, &allset);    while(1){          rset = allset;/*每次循环都应恢复,这一步是最关键的*/      select(maxfd + 1, &rset, NULL, NULL, NULL);      if(FD_ISSET(socket_one, &rset)){          /* 代码*/      }            if(FD_ISSET(socket_two, &rset)){          /*代码*/      }  }

原创粉丝点击