【问题标题】:What is the benefit of using non-blocking sockets with the "select" function?使用带有“选择”功能的非阻塞套接字有什么好处?
【发布时间】:2012-10-07 21:04:20
【问题描述】:

我正在 Linux 中编写一个服务器,它必须支持来自多个客户端的同时读/写操作。我想使用 select 功能来管理读/写可用性。

我不明白的是:假设我想等到套接字有数据可供读取。 select 的文档声明它会阻塞直到有数据可供读取,并且读取函数不会阻塞。

所以如果我使用 select 并且我知道 read 函数不会阻塞,为什么我需要将我的套接字设置为非阻塞?

【问题讨论】:

    标签: sockets unix network-programming


    【解决方案1】:

    在某些情况下,套接字报告为就绪,但当您检查它时,它会更改其状态。

    一个很好的例子是接受连接。当一个新的连接到达时,一个监听套接字被报告为准备好读取。当您调用accept 时,连接可能在发送任何内容之前以及在我们调用accept 之前被另一方关闭。当然,这种情况的处理是依赖于操作系统的,但accept 可能会简单地阻塞,直到建立新的连接,这将导致我们的应用程序无限期地等待阻止其他套接字的处理。如果您的侦听套接字处于非阻塞模式,则不会发生这种情况,您会收到EWOULDBLOCK 或其他错误,但accept 无论如何都不会阻塞。

    一些内核曾经(我希望现在已经修复)一个有趣的 UDP 和 select 错误。当一个数据报到达时select 唤醒套接字,数据报被标记为准备好读取。数据报校验和验证被推迟到用户代码调用recvfrom(或其他一些能够接收UDP数据报的API)。当代码调用recvfrom 并且验证代码检测到校验和不匹配时,数据报被简单地丢弃,recvfrom 最终被阻塞,直到下一个数据报到达。可以在here 找到修复此问题的补丁程序之一(以及问题描述)。

    【讨论】:

      【解决方案2】:

      除了其他人提到的内核错误之外,选择非阻塞套接字(即使使用轮询循环)的另一个原因是它可以在快速到达的数据上实现更高的性能。想想当阻塞套接字被标记为“可读”时会发生什么。您不知道有多少数据已到达,因此您只能安全地读取一次。然后你必须回到事件循环让你的轮询器检查套接字是否仍然可读。这意味着对于套接字的每次读取或写入,您必须至少执行两个系统调用:select 告诉您读取是安全的,以及读取/写入调用本身。

      使用非阻塞套接字,您可以在第一次调用之后跳过对select 的不必要调用。当一个套接字被select 标记为可读时,只要它返回数据,您就可以选择从中读取,这样可以更快地处理快速突发的数据。

      【讨论】:

      • 谢谢,很好,我不知道尝试阅读会比另一个选择更快。
      【解决方案3】:

      这听起来很刺耳,但事实并非如此。使它们成为非阻塞的最好理由是不要阻塞。

      考虑一下。 select() 告诉你有东西要读,但你不知道有多少。可能是 2 个字节,可能是 2,000。在大多数情况下,在返回select 之前耗尽所有数据会更有效。所以你进入一个while循环来读取

      while (1)
      {
          n = read(sock, buffer, 200);
          //check return code, etc
      }
      

      如果没有内容可读,最后一次读取会发生什么?如果套接字不是非阻塞的,您将阻塞,从而(至少部分地)击败select() 的要点。

      【讨论】:

        【解决方案4】:

        其中一个好处是,它可以捕获您犯的任何编程错误,因为如果您尝试读取通常会阻止您的套接字,您将获得 EWOULDBLOCK。对于套接字以外的对象,确切的 api 行为可能会发生变化,请参阅http://www.scottklement.com/rpg/socktut/nonblocking.html

        【讨论】:

          猜你喜欢
          • 2011-08-19
          • 2010-12-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-04-02
          • 2013-10-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多