大家都说select是用在阻塞模式下,如果采用非阻塞模式,我想知道某个socket连接是否可以读,是否可以写该怎么判断啊?希望大虾指教!!

解决方案 »

  1.   

    另外还想问一下如果是非阻塞模式的,利用recv和send函数如果返回SOCKET_ERROR 或0 应该如何处理?
      

  2.   

    select模型一般和多线程结合用,分别建立数据的读写两个线程,在线程里循环判断套接字上是否存在数据,或者能否向一个套接字写入数据
      

  3.   

    楼上的什么意思?对于非阻塞模式,仍然可以用select来判断某个socket是否可以读写吗?如果可以的话能否例个事例?谢谢!
      

  4.   

    仍然可以用select来判断某个socket是否可以读写吗?
    ==
    可以,代码参考
    http://search.csdn.net/Expert/topic/2057/2057746.xml?temp=.6641046
      

  5.   

    还可以用信号驱动吧,用WsaAsyncSelect
      

  6.   

    int mComm::Run() 
    {
    // TODO: Add your specialized code here and/or call the base class
    while (Loop)
    {
    JudgeBlocking();
    MainProc();
    Sleep(1);
    }
    return CWinThread::Run();
    }
    void mComm::JudgeBlocking()
    {
    int i,ti;
    char * telnum;
    SOCKET ts;
    timeval mWaitTime;
    fd_set fdRead,fdWrite; mWaitTime.tv_sec = 0;
    mWaitTime.tv_usec = 0;
    FD_ZERO(&fdRead);
    FD_ZERO(&fdWrite); for (i=0;i<MAXCLIENTNUM;i++)
            {

    ts = theCommApp->GetSocket(i); //得到第i路的socket号
    if(ts!=NULL)
    {
    FD_SET(ts,&fdRead);  
    FD_SET(ts,&fdWrite);
    ti = select(NULL,&fdRead,&fdWrite,NULL,&mWaitTime);
    if (FD_ISSET(ts,&fdRead))
    CanRcvFlag[i] = true;  //判断第i路是否可读
    if (FD_ISSET(ts,&fdWrite))
    CanSendFlag[i] = true; //判断第i路是否可写
    else
    CanSendFlag[i] = false;
    FD_ZERO(&fdRead);
    FD_ZERO(&fdWrite);
     }
             } 
    }int RcvPoint[MAXCLIENTNUM];
    void mComm::MainProc()
    {
    int i,ti;
    ti=0;

    for (i=0;i<MAXCLIENTNUM;i++)
    {
       if (CanRcvFlag[i])
    {
       CanRcvFlag[i] = false;
      ti = recv(theCommApp->GetSocket(i),&Rcvbuff[i][RcvPoint[i]],MAXPACKAGELEN-RcvPoint[i],0);        //MAXPACKAGELEN定义为1000
     if ((ti!=SOCKET_ERROR)&&(ti>0))
    {
                        ……    //读接收到的数据 
                       }
                        else
                      {
                       ……     //出错
                       }
                  }
              }
       }
    为什么CanRcvFlag[i])已经判断为TRUE了,就是有数据可读了,为什么还会出现recv返回SOCKET_ERROR同样用判断出CanSendFlag[i]为TRUE了,为什么send还返回SOCKET_ERROR?为什么select判断的结果和实际的不相符合?????
      

  7.   

    错误代码是多少?
    recv和send函数如果返回SOCKET_ERROR,判断是否为WSAEWOULDBLOCK错误?对于非锁定套接字recv函数返回WSAEWOULDBLOCK说明:没有收到数据,稍后再次检查。
    recv和send函数如果返回0,说明数据接收结束了。
      

  8.   

    若将超时值设置为( 0 , 0),表明s e l e c t会立即返回,允许应用程序对s e l e c t操作进行“轮询”。出于对性能方面的考虑,应避免这样的设置。。s e l e c t成功完成后,会在f d _ s e t结构中,返回刚好有未完成的I / O操作的所有套接字句柄的总量。若超过t i m e v a l设定的时间,便会返回0。不管由于什么原因,假如s e l e c t调用失败,都会返回S O C K E T _ E R R O R。
    判断select返回值了吗?
      

  9.   

    ti = select(NULL,&fdRead,&fdWrite,NULL,&mWaitTime);
    if (FD_ISSET(ts,&fdRead))
    CanRcvFlag[i] = true;  //判断第i路是否可读
    if (FD_ISSET(ts,&fdWrite))
    CanSendFlag[i] = true; //判断第i路是否可写
    else
    CanSendFlag[i] = false;
    上面的语句中select的返回值是2,
    CanSendFlag[i] = true,但是这种情况下send返回的是-1,什么意思?为什么检测到线路是可以发送的, 但是send却发送失败呢?
      

  10.   

    send返回的错误代码是什么?按照返回错误往下查找原因
      

  11.   

    不要把超时设为0,用NULL试试ti = select(NULL,&fdRead,&fdWrite,NULL,NULL);
      

  12.   

    NULL 会阻塞的, 如果仅仅是检查是否可读写, 应将时间设为0
      

  13.   

    时间设为0,s e l e c t会立即返回,应用程序需要对s e l e c t操作进行“轮询”,而楼主好像没有这样做。这就可能是导致问题的原因(我不敢肯定)
      

  14.   

    krh2001(边城浪子)
    如果时间设成0,好象select模型也不能立刻检查到网络的最新情况,比如如果将网络的网线断开,select检查的结果仍然是可发送的,这时send是成功的,但一段时间后会检查到不可发送,如果再将网络恢复,select在一段时间的延迟后select检测可发送(但此时select的返回值是2),但send是-1怎么回事?为什么select检测到网络恢复可以发送了,但send却不能发送呢?
    请解释解释!!!
      

  15.   

    aiyue2010(亚伦) 
    你所说的“轮询”是不是指不停地用select检查网络的状况??我是基本不停的在用select检查的,如果不是,你的“轮询”指的是什么?