带 Select 的非阻塞套接字

发布于 2024-08-17 00:10:46 字数 245 浏览 10 评论 0原文

我不明白在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

段念尘 2024-08-24 00:10:46

有一个关于执行高容量 I/O 的所有不同选项的精彩概述,名为 C10K 问题。它对许多不同的选项进行了相当完整的调查,至少截至 2006 年。

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

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

是的,您可以使用非阻塞套接字,然后有一个循环,如果没有准备好,则等待,但与使用诸如 select 或更现代的替代品之一(>epollkqueue 等)。我想不出为什么有人会真正想要这样做的原因;所有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:

Note: it's particularly important to remember that readiness notification from the kernel is only a hint; the file descriptor might not be ready anymore when you try to read from it. That's why it's important to use nonblocking mode when using readiness notification.

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 the select 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.

七堇年 2024-08-24 00:10:46

selectpollepollkqueue 等工具针对多个套接字/文件描述符处理场景。想象一下一个负载沉重的网络服务器,有数百个同时连接的套接字。您如何知道何时读取以及从哪个套接字读取而不阻塞一切?

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 to read and from what socket without blocking everything?

公布 2024-08-24 00:10:46

如果您在非阻塞套接字上调用 read,如果自上次调用 read 后没有收到任何数据,它将立即返回。如果您只阅读,并且想要等到有可用数据,则必须忙等待。这会浪费CPU。

pollselect (和朋友)允许您休眠,直到有数据要读取(或写入,或收到信号等)。

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

If you call read on a non-blocking socket, it will return immediately if no data has been received since the last call to read. If you only had read, and you wanted to wait until there was data available, you would have to busy wait. This wastes CPU.

poll and select (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.

心如狂蝶 2024-08-24 00:10:46

对于你的第一个问题,这种情况没有什么区别。唯一的区别是当没有什么可读的时候他们会做什么。由于您在调用 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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文