*nix 平台下:
   if (FD_ISSET(socket, &readfds))
       printf("Data comes ...\n");
   else
       printf("Timed out.\n");
但Windows下MSDN里说:
FD_ISSET(s, *set) 
   Nonzero if s is a member of the set. Otherwise, zero. 
那么FD_ISSET的真实作用是什么?select 与 fd_set 是如何工作的?(一直不明白,看MSDN看晕了)谢谢!

解决方案 »

  1.   

    int select(
      int nfds,                           
      fd_set FAR *readfds,               
      fd_set FAR *writefds,              
      fd_set FAR *exceptfds,             
      const struct timeval FAR *timeout  
    );
    如上述,select中需要几个fd_set结构的参数,用来指定你所care的socket。
    下面四个宏被定义用来使操作fd_set结构更简单:
    FD_CLR(s, *set) 
    从fd_set结构:set中删掉s指明的套接字 
    FD_ISSET(s, *set) 
    判断套接字s是否在set中,返回非0则证明s在set中。反之不在。
    FD_SET(s, *set) 
    把套接字s加入到set中
    FD_ZERO(*set) 
    初始化set,全置0 
      

  2.   

    这是判断socket是否有数据可读/可写用的。 FD_ZERO(&fdRead) ; // 清空读
    FD_SET((unsigned int)YourSocketId,&fdRead);
    int ret = select(0,&fdRead,NULL,NULL,&tmvTimeout);
                      if (ret == SOCKET_ERROR)
    { // select 函数出错
                         printf("Select() Socket error: %d..\n",GetLastError ());
       continue;
    }
    else if (ret > 0)
                       {// 有数据可读,数据处理
                        } 
                      else if (ret==0)
                        {// 没有数据可读
                         }     
      

  3.   

    四个宏的定义如下:#define FD_CLR(fd, set) do {     u_int __i;     for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count ; __i++) {         if (((fd_set FAR *)(set))->fd_array[__i] == fd) {             while (__i < ((fd_set FAR *)(set))->fd_count-1) {                 ((fd_set FAR *)(set))->fd_array[__i] =                     ((fd_set FAR *)(set))->fd_array[__i+1];                 __i++;             }             ((fd_set FAR *)(set))->fd_count--;             break;         }     } } while(0)#define FD_SET(fd, set) do {     u_int __i;     for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) {         if (((fd_set FAR *)(set))->fd_array[__i] == (fd)) {             break;         }     }     if (__i == ((fd_set FAR *)(set))->fd_count) {         if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) {             ((fd_set FAR *)(set))->fd_array[__i] = (fd);             ((fd_set FAR *)(set))->fd_count++;         }     } } while(0)#define FD_ZERO(set) (((fd_set FAR *)(set))->fd_count=0)#define FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set FAR *)(set))
      

  4.   

    当select返回的时候,相应的fd_set结构中会存有导致它返回的那个socket,例如某个socket有数据到来,那么select返回的fd_set FAR *readfds中就含有那个socket。通过用FD_ISSET判断,可以知道是哪个套接字上有数据到来了,以便调用recv接收。
      

  5.   

    也就是说select会操作并改变 fd_set 集合,是吗?
      

  6.   

    msdn have an example about this:
    Simple: Sample TCP/UDP server
    you can search this example in MSDN
      

  7.   


    说明白一些:我想知道select是如何工作的。
    也就是说,如果FD_SET(socket, &set)了,那么socket肯定在set中
    FD_ISSET(socket, &set)应该是真。那么select返回后,它是否把没有数据的socket从set中删除了呢?谢谢!
      

  8.   

    举个例子说一下:fd_set fs;    // 声明一个fd_set结构,用于判断是否有数据到来
    FD_ZERO(&fs); // 清零
    FD_SET(s1, &fs);// 将套接字s1加入到结构中
    FD_SET(s2, &fs);int ret = select(0, &fs, NULL, NULL, NULL)// 等候s1 s2两个套接字上的数据到来
    if(FD_ISSET(s1, &fs))
    {
       // select返回的时候,会改写fs,在里面填入可读(即有数据等待接收)的套接字
       // 此处用FD_ISSET判断,fs中存在s1,则s1上有数据等待接收
       recv(s1, ……);
    }
    if(FD_ISSET(s2, &fs))
    {
       // select返回的时候,会改写fs,在里面填入可读(即有数据等待接收)的套接字
       // 此处用FD_ISSET判断,fs中存在s2,则s2上有数据等待接收
       recv(s2, ……);
    }……
      

  9.   

    它表示你所设置集合里的socket是不是处于可读状态,
    如果先select调用,再用FD_ISSET()宏进行测试表示socket仍在集合里,
    所以已便判断当前测试的socket是否有字符要读,那么这时应用程序可以
    调用Receive()可以进行读取了。
      

  10.   

    就是像你说的那样
    select会操作并改变 fd_set 集合,重新分配socket到应该在的集合。