使用默认创建的阻塞SOCKET,在线程中执行select对socket进行可读的监控,select返回1,但是FD_ISSET为FALSE,无法执行recv,请教一下 为什么?//线程函数中..
fd_set RSet;
FD_ZERO(&RSet);
FD_SET (hSocket,&RSet);struct timeval tv;
tv.tv_sec = 30;
tv.tv_usec = 0;int nRet = select(hSocket,&RSet,NULL,NULL,&tv);  //nRet 返回1
if (nRet > 0)
{
  if (FD_ISSET(hSocket,&RSet))  //判断为假,recv无法执行
  {
    nRet = recv(hSocket,...) 
  }]

解决方案 »

  1.   

    select的第一个参数其实是不用的,填0即可,
    建议把writefds,exceptfds也传上去,返回1可能是发生异常也说不定,
    每个都判断一下就知道是可读,可写,还是发生异常了
      

  2.   

    不太明白 exceptfds怎么样用法?
    FD_SET (??,&exceptfds);
    ??放什么异常对象?
      

  3.   

    select调用参数错误,你是linux平台吧?必须设置第一个参数为hSocket+1,可以看看man页,有详细说明的。如下:int nRet = select(hSocket+1,&RSet,NULL,NULL,&tv);  //nRet 返回1
      

  4.   

    另外,对于reayi的回复,个人看法如下:
      如果不需要检测是否可写,则 writefd 是需要设置为 NULL 的,至于 exceptfd 用来检测带外数据,正常的通信是用不到的,网络通信中只有有必要传输紧急数据时才用,因此绝大部分的 exceptfd 需要设置为 NULL。
      linux和windows下select调用差别主要在两分面:
       1. windows下第一个参数无所谓设置成多少,linux必须为管理的最大套接字加1。
       2. windows下最后一个参数以常量的形式传递进去,不会被更改,linux下会更改该值为剩余的时间。
      在做高并发管理时候,后者很容易导致讯里面的高cpu耗用,处理方法是在每个select前面重置timeout或者相关策略。
      

  5.   

    nRet 返回值为1
    如果
    //线程函数中..
    fd_set errorfds;
    FD_ZERO(&errorfds);
    FD_SET (hSocket,&errorfds);fd_set RSet;
    FD_ZERO(&RSet);
    FD_SET (hSocket,&RSet);struct timeval tv;
    tv.tv_sec = 30;
    tv.tv_usec = 0;int nRet = select(hSocket,&RSet,NULL,&errorfds,&tv);  //nRet 返回1
    if (nRet > 0)
    {
     if (FD_ISSET(hSocket,&errorfds))  //判断为假,弹对话框无法执行
      {
        AfxMessageBox("error");
      }
      if (FD_ISSET(hSocket,&RSet))  //判断为假,recv无法执行
      {
        nRet = recv(hSocket,...) 
      }]不知道那样判断错误对不对?返回值仍然为1.但是检测不到有事件,FD_ISSET老是0
      

  6.   

    是因为你在FD_ISSET(hSocket,&RSet)时,RSet中已为0.你调试的时候可以看下
      

  7.   


    不好意思,在Windows 没有找打类似 fd_isempty,请教 怎么样判断?
    如果为空的话,可能是什么原因造成的?
      

  8.   

    真得很奇怪,我在自己的机器上执行了一下,没有出现你说的这种情况,机器配置:windows server 2003+vc6.0