int select(
  __in      int nfds,
  __in_out   fd_set* readfds,
  __in_out   fd_set* writefds,
  __in_out   fd_set* exceptfds,
  __in      const struct timeval* timeout
);
“select模型”是利用select函数来管理I/O。select函数可用于判断套接字上是否存在数据,或者能否向一个套接字写入数据。比如可以先调用select函数判断能否从某个套接字读数据,以避免直接调用recv进入阻塞状态(或者在非阻塞模式时产生WSAEWOULDBLOCK错误)。其中readfds用于检查可读性,readfds集合包含符合下述任何一个条件的套接字:
1. 有数据可以读入
2. 连接已经被关闭、重启或终止(这时recv也可以立即返回,返回值为0或WSAECONNRESET等)
3. 假如已调用了listen,而且有一个连接正处于搁置状态,那么accept函数调用会成功(《windows网络编程》)。这第3条是在《windows网络编程》上看到的,我没有理解作者表达的意思。是处于这个状态的sokcet,调用recv也可以立即返回吗?请大家帮忙释疑。谢谢-_-。
winsockselect

解决方案 »

  1.   

    我查了一下MSDN,原文如下:readfds:
    If listen has been called and a connection is pending, accept will succeed. 
    Data is available for reading (includes OOB data if SO_OOBINLINE is enabled). 
    Connection has been closed/reset/terminated. writefds:
    If processing a connect call (nonblocking), connection has succeeded. 
    Data can be sent. exceptfds:
    If processing a connect call (nonblocking), connection attempt failed. 
    OOB data is available for reading (only if SO_OOBINLINE is disabled). 主要就是红色字体的这两行,不太明白。应该是我对TCP的各种状态不了解的原因。希望大家帮忙解释一下。谢谢。
      

  2.   

    学习很认真么
    我从来都是忽略这种细节的
    字面理解就是出于搁置状态的socket也属于accept成功的范畴
      

  3.   

    The accept function extracts the first connection on the queue of pending connections on socket s. It then creates and returns a handle to the new socket. accept从队列中提取第一个即将连接的socket!
      

  4.   


    谢谢版主回帖,追问一下。-_-
    readfds 是用来检查可读性的,那处于这个状态“If listen has been called and a connection is pending, accept will succeed. ”的socket,会被系统放置到readfds 集合中。那说明处于“If listen has been called and a connection is pending, accept will succeed. ”状态的socket就是可写的吗?或者这个状态的socket,调用recv不会阻塞吗? 
      

  5.   


    处于这个状态的socket,你还没accept返回,如何去recv?
      

  6.   

    accept成功之后,你才可以调用send,recv。至于recv是否阻塞,需要看你使用什么网络模型。
      

  7.   


    对啊。我的疑问就在此,既然这个socket不能recv,为何还要包含在select的readfds集合里面?
    这里的模型,就是普通的select模型。readfds用于检测可读性,难道这里所谓的可读性,就是说recv能马上读回数据,或者不能读回数据,但可以马上返回,不阻塞?可能我上面没说清问题?我的疑问就是处于“If listen has been called and a connection is pending, accept will succeed. ”这个状态的的socket,为什么会在select返回之后,包含在readfds集合中?谢谢。-_-
      

  8.   


    select返回信息说明的是socket的可能状态, 具体这些socket处于什么状态, 要看你使用的socket的环境, 比如返回的readfds中有个SOCKET s 等于你的socket, 如果你的socket处于listen状态, 那么这时select的返回就表示该socket可以成功的accept, 对于其他状态的socket则表示可以无阻塞的调用接收; 对于面向连接的socket, 也可能表示连接已关闭,这时可以根据recv的结果来判断。PS:我也是看MSDN这么理解的, 具体自己没用过。
      

  9.   


    我看了你的解释,又去找了下msdn,我觉得应该就是你说的这意思。谢谢。我主要看书了,msdn的内容没看仔细。我把msdn的原话贴在下面:The parameter readfds identifies the sockets that are to be checked for readability. If the socket is currently in the listen state, it will be ed as readable if an incoming connection request has been received such that an accept is guaranteed to complete without blocking. For other sockets, readability means that queued data is available for reading such that a call to recv, WSARecv, WSARecvFrom, or recvfrom is guaranteed not to block.For connection-oriented sockets, readability can also indicate that a request to close the socket has been received from the peer. If the virtual circuit was closed gracefully, and all data was received, then a recv will return immediately with zero bytes read. If the virtual circuit was reset, then a recv will complete immediately with an error code such as WSAECONNRESET. The presence of OOB data will be checked if the socket option SO_OOBINLINE has been enabled (see setsockopt).
      

  10.   

    你概念理解错了,呵呵。select不仅仅适用于普通socket的recv,send,也适用于listen socket。如果readfds包含了listen socket(姑且叫listenSocket),意味着,此时如果你去accept这个listenSocket会成功返回一个新的socket,姑且叫acceptSocket。对于listenSocket,你不应该去recv或send他,因为他是listen socket,不负责数据通讯,只负责accept新的client socket。你应该考虑的是针对acceptSocket,如何调用recv,send来接送或者发送数据。如果你把acceptSocket加到readfds中,当select触发readfds,并且readfds中包含acceptSocket,这才意味着你可以去recv这个acceptSocket了。别弄混了listen socket与普通通讯socket。
      

  11.   

    是的
    你的概念混淆了
    select也可以设置accept事件
    我们都是围绕这个说的
    而你一味强调recv
    这......