3

我不明白在选择返回它已准备好读取之后等待调用 recv() 后在非阻塞套接字上调用 recv() 与阻塞套接字之间有什么区别。在我看来,阻塞套接字无论如何都不会在这种情况下阻塞。
另外,我听说使用非阻塞套接字的一种模型是在经过一段时间后尝试对它们进行调用(recv/send/etc),而不是使用诸如 select 之类的东西。与使用类似 select 的东西相比,这种技术似乎很慢而且很浪费(但是我根本没有达到上述非阻塞的目的)。这在当今的网络编程中很常见吗?

4

4 回答 4

3

有一个很好的概述了进行大容量 I/O 的所有不同选项,称为C10K 问题。至少截至 2006 年,它对许多不同的选项进行了相当完整的调查。

引用它,关于在select非阻塞套接字上使用的主题:

注意:特别重要的是要记住来自内核的就绪通知只是一个提示;当您尝试从中读取文件描述符时,它可能不再准备就绪。这就是为什么在使用就绪通知时使用非阻塞模式很重要的原因。

是的,你可以使用非阻塞套接字,然后有一个循环等待,如果没有准备好,但与使用类似select或更现代的替代品之一(epoll,kqueue等)相比,这是相当浪费的。我想不出任何人真正想要这样做的原因。所有select类似的选项都可以设置超时,因此您可以在一定时间后被唤醒以执行一些常规操作。我想如果你正在做一些相当 CPU 密集型的事情,比如运行一个视频游戏,你可能不想睡觉,而是继续计算,同时使用非阻塞套接字定期检查 I/O。

于 2010-01-06T19:33:04.853 回答
1

, select, poll,epollkqueue工具针对多个套接字/文件描述符处理场景。想象一个负载很重的 Web 服务器,它有数百个同时连接的套接字。在不阻塞所有内容的情况下,您如何知道何时read进出哪个套接字?

于 2010-01-06T19:02:11.920 回答
0

如果您调用read非阻塞套接字,如果自上次调用以来没有收到任何数据,它将立即返回read。如果您只有read,并且您想等到有可用数据,您将不得不忙着等待。这会浪费 CPU。

poll并且select(和朋友)允许您睡觉,直到有数据要读取(或写入,或接收到信号等)。

如果您唯一要做的就是在该套接字上发送和接收,那么您不妨只使用非阻塞套接字。当您同时有其他事情要做时,异步很重要,例如更新 GUI 或处理其他套接字。

于 2010-01-06T19:20:56.203 回答
0

对于您的第一个问题,这种情况没有区别。唯一的区别是当没有什么可读的时候他们会做什么。由于您在调用 recv() 之前检查了这一点,因此您不会看到任何区别。

对于第二个问题,我在所有库中看到的方法是使用 select、poll、epoll、kqueue 来测试数据是否可用。从性能的角度来看,select 方法是最古老的,也是最不可取的(特别是对于管理大量连接)。

于 2010-01-06T19:22:52.533 回答