【问题标题】:Epoll epollin read dataepoll epollin 读取数据
【发布时间】:2012-04-04 14:47:49
【问题描述】:

在我接受设置为侦听EPOLLIN 事件的连接套接字之后使用epoll,并且我收到EPOLLIN 事件,我是否必须在epoll_ctl 之前读取所有数据(直到0)只有EPOLLOUT

示例:我有一个使用 epoll 的 HTTP 服务器,我只想读取(EPOLLINrecv)HTTP 标头,直到 \r\n\r\n。我可以安全地忽略消息的其余部分而不阅读它并切换到输出(EPOLLOUTsend)吗?

【问题讨论】:

  • 如果使用边沿触发,你可以做到。但是,如果您不读取剩余的输入数据,那么它将在套接字输入缓冲区中,直到您关闭套接字,并且它可能会填满缓冲区(可能非常小)。

标签: c linux epoll


【解决方案1】:

简短的回答是肯定的,它是安全的。一些事情。

“读取所有数据直到 0”的替代方案实际上无论如何都行不通。浏览器客户端在使用来自服务器的响应之前不会关闭/关闭其套接字末端。因此,您将等待 recv 返回 0,因为远程客户端仍在等待您响应。

假设您没有使用边缘触发模式,您应该没问题,而不必担心错过任何通知。您可以仅使用带有 EPOLLIN 通知和 recv() 的标头,然后使用 epoll_ctl 套接字来接收 EPOLLOUT 通知。当您完成发送响应后,安全的做法是切换回监听 EPOLLIN 通知(可能还有 EPOLLHUP 和 EPOLLRDHUP)以消耗请求中的任何额外数据,直到客户端关闭他的套接字(在这种情况下,recv 将返回 0 )。

也可以使用边缘触发模式。只要确保使用非阻塞套接字并在切换到响应模式时尝试非阻塞发送,即使您没有获得初始 EPOLLOUT。切换回阅读模式时,请执行非阻塞接收,以防您丢失了早期的 EPOLLIN。

如果一个愚蠢的客户端尝试发送的不仅仅是标头(如一长串 POST 数据字节),则客户端可能在完成发送之前不会尝试接收响应。因此,您会陷入虚拟死锁。服务器和客户端都不能向它们的套接字写入额外的字节,因为双方都没有读取。简单的解决方案是确保在发送响应之前消耗整个请求(标头和“Content-Length”字节)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-11
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-29
    相关资源
    最近更新 更多