socket select()与非block recv

时间:2013-10-03 21:16:01

标签: c sockets nonblocking recv posix-select

我看过一些比较select()poll()epoll()的文章,我看过很多指南讨论select()与多个recv()的实际用法套接字。

但是,我似乎找不到的是与没有select()的非阻止select()通话进行比较。如果只有1个套接字要读取,1个套接字要写入,是否有理由使用recv()调用?可以将WSAEWOULDBLOCK方法设置为在没有可用数据时不阻止并返回错误(select()),那么当您没有其他套接字要检查时,为什么还要调用recv()?非阻塞{{1}}调用是否慢得多?

3 个答案:

答案 0 :(得分:9)

当你无限制地轮询cpu时间时,你不希望在没有其他方法等待套接字数据的情况下对recv进行非阻塞调用。

如果您没有其他套接字要检查,并且在同一个线程中没有其他任何操作,则阻塞调用read可能是最有效的解决方案。虽然在这种情况下,考虑到这种效率就像是过早优化。

随着套接字数量的增加,这些考虑因素才会发挥作用。

非阻塞调用仅在处理单个线程上的多个套接字的上下文中更快。

答案 1 :(得分:5)

select()和朋友们让你设计工作流程,使得一个套接字的缓慢不会妨碍你为另一个套接字服务的速度。想象一下,数据从接收套接字快速到达,并且您希望尽可能快地接受它并存储在内存缓冲区中。但发送套接字很慢。当你填满操作系统的发送缓冲区并且send()给你EWOULDBLOCK时,你可以发出select()来等待接收和发送套接字。如果接收套接字上的新数据到达,或者某些缓冲区被释放,并且您可以将更多数据写入发送套接字,则先发生select()

当然,select()的更实际的用例是当您有多个套接字要读取和/或写入时,或者必须在两个方向上的两个套接字之间传递数据时。

事实上,select()告诉您何时知道套接字上的下一个读取或写入操作是否成功,所以如果您只在select允许的情况下尝试读写,那么即使您的程序也几乎可以正常工作没有使插座无阻塞!这样做仍然是不明智的,因为尽管select()报告套接字为“就绪”,但下一个操作仍可能阻塞时存在边缘情况。

另一方面,由于reason explained by @Troy,因此几乎不建议使用非阻塞且不使用select()的套接字。

答案 2 :(得分:3)

如果没有可用数据,并且您使用非阻塞IO,recv()将立即返回。 然后该程序应该做什么?您需要在循环中调用recv()直到数据可用 - 这只是使用CPU几乎没有理由。

recv()上旋转并以这种方式刻录CPU是非常不可取的;你宁愿让这个过程等到数据可用并被唤醒;这是select()/poll()和类似的内容。

并且,循环中的sleep()以便不燃烧CPU也不是一个好的解决方案。您在处理过程中会引入高延迟,因为只要数据可用,程序就无法处理数据。