11

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

谁能给我一个实际使用POLLOUT的例子吗?

4

3 回答 3

22

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

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

从 nginx 来源,我发现:

如果有一些数据要发送出去,nginx 会尝试使用系统调用(可能是 writev)发送它。但是,如果 nginx 不能一次发送总数据,它会在 pollfd 上设置 POLLOUT,如果使用 poll 事件,则等待可写事件。当得到一个可写事件时,nginx会发送剩下的数据。

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

于 2014-02-21T03:56:44.527 回答
0

在 Raspberry PI 3、Debian 上工作,使用 c++ 98 和 gcc 。. .

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

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

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

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

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

于 2018-04-18T19:12:09.170 回答