【问题标题】:Nonblocking sockets with Select使用 Select 的非阻塞套接字
【发布时间】:2010-01-06 18:54:48
【问题描述】:

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

【问题讨论】:

    标签: c networking nonblocking


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 当需要低延迟并且浪费周期被一些 $$$ 所覆盖时,这种繁忙的循环相当普遍(阅读 - 金融行业:)。基本上,这个想法是不要让内核在系统调用中休眠,从而至少间隔两次上下文切换。
    • 很公平。因此,您可能会这样做是有一些原因的,但对于大多数应用程序,您通常希望使用select like 循环。
    【解决方案2】:

    selectpollepollkqueue 等工具针对多个套接字/文件描述符处理场景。想象一个负载很重的 web 服务器,它有数百个同时连接的套接字。你怎么知道什么时候到read 以及从哪个套接字而不阻塞一切?

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

        • select 可能表明一个套接字是可读的,但是当你去读取它时它没有可用的数据。这在很大程度上是一种边缘情况,但它可能发生在接收到校验和错误的数据包(仅在应用程序读取数据时才检查)这样的情况下。
        猜你喜欢
        • 1970-01-01
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-29
        • 2010-10-31
        • 2013-10-15
        相关资源
        最近更新 更多