带 Select 的非阻塞套接字
我不明白在 select 返回它已准备好读取后等待调用 recv() 后,在非阻塞套接字上调用 recv() 与阻塞套接字之间有什么区别。在我看来,阻塞套接字在这种情况下永远不会阻塞。
另外,我听说使用非阻塞套接字的一种模型是尝试在经过一段时间后对其进行调用(recv/send/等),而不是使用诸如 select 之类的东西。与使用诸如 select 之类的技术相比,这种技术似乎缓慢且浪费(但随后我根本不明白如上所述的非阻塞的目的)。这在当今的网络编程中很常见吗?
I do not understand what the difference is between calling recv() on a non-blocking socket vs a blocking socket after waiting to call recv() after select returns that it is ready for reading. It would seem to me like a blocking socket will never block in this situation anyway.
Also, I have heard that one model for using non blocking sockets is try to make calls (recv/send/etc) on them after some amount of time has passed instead of using something like select. This technique seems slow and wasteful to be compared to using something like select (but then I don't get the purpose of non-blocking at all as described above). Is this common in networking programming today?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
有一个关于执行高容量 I/O 的所有不同选项的精彩概述,名为 C10K 问题。它对许多不同的选项进行了相当完整的调查,至少截至 2006 年。
引用其中关于在非阻塞套接字上使用
select
的主题:是的,您可以使用非阻塞套接字,然后有一个循环,如果没有准备好,则等待,但与使用诸如
select
或更现代的替代品之一(>epoll
、kqueue
等)。我想不出为什么有人会真正想要这样做的原因;所有select
之类的选项都可以设置超时,因此您可以在一定时间后被唤醒以执行某些常规操作。我想如果你正在做一些 CPU 密集型的事情,比如运行视频游戏,你可能不想睡觉,而是继续计算,同时使用非阻塞套接字定期检查 I/O。There's a great overview of all of the different options for doing high-volume I/O called The C10K Problem. It has a fairly complete survey of a lot of the different options, at least as of 2006.
Quoting from it, on the topic of using
select
on non-blocking sockets:And yes, you could use non-blocking sockets and then have a loop that waits if nothing is ready, but that is fairly wasteful compared to using something like
select
or one of the more modern replacements (epoll
,kqueue
, etc). I can't think of a reason why anyone would actually want to do this; all of theselect
like options have the ability to set a timeout, so you can be woken up after a certain amount of time to perform some regular action. I suppose if you were doing something fairly CPU intensive, like running a video game, you may want to never sleep but instead keep computing, while periodically checking for I/O using non-blocking sockets.select
、poll
、epoll
、kqueue
等工具针对多个套接字/文件描述符处理场景。想象一下一个负载沉重的网络服务器,有数百个同时连接的套接字。您如何知道何时读取
以及从哪个套接字读取而不阻塞一切?The
select
,poll
,epoll
,kqueue
, etc. facilities target multiple socket/file descriptor handling scenarios. Imagine a heavy loaded web-server with hundreds of simultaneously connected sockets. How would you know when toread
and from what socket without blocking everything?如果您在非阻塞套接字上调用
read
,如果自上次调用read
后没有收到任何数据,它将立即返回。如果您只阅读
,并且想要等到有可用数据,则必须忙等待。这会浪费CPU。poll
和select
(和朋友)允许您休眠,直到有数据要读取(或写入,或收到信号等)。如果您唯一要做的就是在该套接字上发送和接收,那么您不妨使用非阻塞套接字。当您同时有其他事情要做时(例如更新 GUI 或处理其他套接字),异步非常重要。
If you call
read
on a non-blocking socket, it will return immediately if no data has been received since the last call toread
. If you only hadread
, and you wanted to wait until there was data available, you would have to busy wait. This wastes CPU.poll
andselect
(and friends) allow you to sleep until there's data to read (or write, or a signal has been received, etc.).If the only thing you're doing is sending and receiving on that socket, you might as well just use a non-blocking socket. Being asynchronous is important when you have other things to do in the meantime, such as update a GUI or handle other sockets.
对于你的第一个问题,这种情况没有什么区别。唯一的区别是当没有什么可读的时候他们会做什么。由于您在调用 recv() 之前进行了检查,因此您不会发现任何差异。
对于第二个问题,我在所有库中看到的做法是使用 select、poll、epoll、kqueue 来测试数据是否可用。 select 方法是最古老的,从性能角度来看也是最不理想的(特别是管理大量连接时)。
For your first question, there's no difference in that scenario. The only difference is what they do when there is nothing to be read. Since you're checking that before calling recv() you'll see no difference.
For the second question, the way I see it done in all the libraries is to use select, poll, epoll, kqueue for testing if data is available. The select method is the oldest, and least desirable from a performance standpoint (particularly for managing large numbers of connections).