2014-10-02 33 views
1

我正处于游戏场景中。服务器和客户端都以高速率通过非阻塞UDP交换消息。理解套接字编程中的select()

(这里可能有些奇怪......)遗留代码也使用select()并将timeout值设置为0,这意味着select()不会阻塞。 Select()在永久while循环内。在select()返回一个大于0的数字时,下面的代码通过recvfrom()接收消息。如果它返回0,下面的代码不会尝试接收。

从打印输出信息中,我看到select()有时返回1(大于0)。我很困惑,因为timeout被设置为0,select()如何有时间检查消息是否准备好从任何readfds读取?谢谢。

回答

1

根据the spec

成功完成后,将PSELECT()或选择()函数应 修改的对象指向了readfds,writefds和errorfds 参数指示哪些文件描述符准备好读取, 准备好写入,或者有一个待处理的错误条件,分别为 ,并返回所有 输出集中就绪描述符的总数。对于每个小于nfds的文件描述符,如果在输入时设置了 ,并且相关条件对于该文件 描述符成立,则应在成功完成时设置对应位。

如果没有选定的描述符准备好用于请求的操作,则pselect()或select()函数应该阻塞,直到至少有一个请求的操作准备就绪,直到发生超时或者直到被信号。 timeout参数控制在超时之前pselect()或select()函数应该执行多长时间。如果超时参数不是空指针,则它指定等待选择完成的最大时间间隔。如果指定的时间间隔没有任何请求的操作准备就绪,则该函数应返回。如果timeout参数是一个空指针,那么对pselect()或select()的调用将无限期地阻塞,直到至少有一个描述符符合指定的条件。 要进行轮询,timeout参数不应该是空指针,而应该指向一个零值的timespec结构。

总之,在检查超时之前检查描述符。如果在调用select()时套接字已准备好数据,则超时被忽略,并且select()立即退出。

+0

谢谢。你能否解释为什么他们同时使用select()和non-blocking来实现即时回报?如果select()返回0,则遗留代码不会接收 - 在select()后立即返回;否则(select()返回1),这应该意味着已经有一些数据准备好接收了,因此可以安全地在没有任何阻塞时间的情况下接收它们 - 在recvfrom()之后立即返回。由于两种情况中的任何一种都能保证立即返回,为什么还要将套接字设置为非阻塞?我的理解是否正确? – Nairan 2014-10-11 13:27:25

+0

从历史上看(在Linux之前),在阻塞套接字上的'select'后面跟着'read'永远不会阻塞,而POSIX仍然需要这个。但是Linux故意违反了POSIX,因为Linux开发人员认为POSIX要求“不可能实现”,尽管BSD自1980年代中期开始实施并实施。有关详细信息,请参阅https://lkml.org/lkml/2011/6/18/76和后续信息。 – Nemo 2014-10-11 17:51:49

+0

谢谢,尼莫。 – Nairan 2014-10-15 14:56:24