何时使用poll C函数的POLLOUT事件?

我用socket() + POLLIN poll() + recv() + send()编写了一个小型TCP服务器,但我不知道何时使用POLLOUT轮询或选择writefds来轮询可写事件。

谁能给我一个POLLOUT真正用法的例子

通常的模式是使用poll()的非阻塞文件描述符,如下所示:

  • 准备好poll()
    • 总是设置POLLIN因为你总是有兴趣阅读套接字的另一端送你的内容。
      • 除非您有大量的传入数据积压,并且您有意在发送更多数据之前让另一端等待。
    • 仅当您有未完成的数据发送到另一端时才设置POLLOUT
  • poll()返回时,如果它指示数据可供读取,
    • 阅读它并用它做点什么
  • poll()返回时,如果它指示套接字是可写的,
    • 尝试发送您的优秀数据。
      • 如果你设法编写了所有这些,那么下次循环时你就不会设置POLLOUT
      • 如果你只是设法发送了一些(或者没有),那么请保留其余部分。 您将在下一次循环时设置POLLOUT
  • 当您要发送新数据时(响应您阅读的数据或响应某些外部事件),您有两种选择:
    • 急切地尝试立即发送一些。 您可以成功发送任何,部分或全部内容。 与前一种情况一样,保留下次未写入的数据部分,并计划在下一次循环时设置POLLOUT ,只有剩下一些数据。
    • 只需保留数据并计划在下一次循环时设置POLLOUT 。 (这种选择通常更容易编程,因为您只需要处理在循环中的一个位置写入数据,但另一方面它会延迟写入数据直到下一次循环。)

从nginx源码,我发现:

如果有一些数据要发送出来,nginx会尝试使用系统调用(也许是writev)发送它。 但是,如果nginx不能一次发送总数据,它将在pollfd上设置POLLOUT,如果使用poll事件,则等待可写事件。 获取可写事件时,nginx将发送左侧数据。

当nginx尝试响应大型静态文件时,很容易重现这种情况

使用带有gcc的c ++ 98,使用Raspberry PI 3,Debian。 。 。

在Acceptor / Connector模式和Reactor / Proactor / ACT模式的实现中,我按照以下顺序定期使用POLLOUT:

  1. 使用套接字函数打开套接字。
  2. 使用fcntl将套接字文件描述符设置为非阻塞模式。
  3. 调用connect并检查返回码。

在大多数情况下,connect返回-1。 由于非阻塞文件描述符,这很可能。 然后我检查结果代码。

如果它是EINPROGRESS,我在反应堆(使用ppoll或epoll)和POLLOUT中注册一个事件处理程序。 最终完成连接后,poll将返回POLLOUT设置。

然后我创建一个新的TcpConnection类并进行通信。