我用socket()
+POLLINpoll()
+recv()
+send()
编写了一个小型TCP服务器,但我不知道何时使用POLLOUT轮询或选择writefds
对可写事件进行轮询。
有人能给我一个POLLOUT的真实用法示例吗?
通常的模式是使用poll()
的非阻塞文件描述符,如下所示:
- 当准备好CCD_ 7时,
- 始终设置
POLLIN
,因为您总是对读取套接字的另一端发送给您的内容感兴趣。- 除非您有大量的传入数据积压,并且您有意让另一端在发送更多数据之前等待
- 仅当您有未处理的数据要发送到另一端时,才设置
POLLOUT
- 始终设置
- 在从
poll()
返回时如果指示数据可用于读取,- 阅读它并用它做点什么
- 如果从
poll()
返回指示套接字是可写的,- 尝试发送未处理的数据。
- 如果您成功地写入了所有内容,那么下次就不会通过循环设置
POLLOUT
- 如果你只寄了一部分(或者没有寄),那么把剩下的留着以后用。您将在下一次循环中设置
POLLOUT
- 如果您成功地写入了所有内容,那么下次就不会通过循环设置
- 尝试发送未处理的数据。
- 当您有新数据要发送时(响应读取的数据或响应某个外部事件),您有两种选择:
- 急切地想马上送一些。您可能不会成功发送任何数据、部分数据或全部数据。就像上一种情况一样,保留下一次未写入的数据部分,并计划在下一次循环中设置
POLLOUT
,前提是还剩下一些数据 - 只需保留数据,并计划在下一次循环中设置
POLLOUT
。(这种选择通常更容易编程,因为您只需要在循环中的一个位置处理写入数据,但另一方面,它会将写入数据延迟到下一次循环。)
- 急切地想马上送一些。您可能不会成功发送任何数据、部分数据或全部数据。就像上一种情况一样,保留下一次未写入的数据部分,并计划在下一次循环中设置
从nginx源代码中,我发现:
如果有一些数据要发送,nginx会尝试使用syscall(可能是writev)发送。但是,如果nginx不能一次发送全部数据,它会在pollfd上设置POLLOUT,如果使用poll事件,则等待可写事件。当得到一个可写事件时,nginx会发送剩下的数据。
当nginx试图响应大型静态文件
在Raspberry PI 3上工作,Debian,使用带有gcc的c++98。
在Acceptor/Connector模式和Reactor/Proactor/ACT模式的实现中,我经常按以下顺序使用POLLOUT:
- 使用套接字功能打开套接字
- 使用fcntl将套接字文件描述符设置为非阻塞模式
- 调用connect并检查返回代码
在大多数情况下,connect返回-1。由于存在非阻塞文件描述符,所以很可能会出现这种情况。然后我检查结果代码。
如果是EINPROGRESS,我会在带有POLLOUT的reactor(使用ppoll或epoll)中注册一个事件处理程序。当连接最终完成时,poll将返回并设置POLLOUT。
然后我创建了一个新的TcpConnection类并进行通信。