使用 `read` 和 `epoll` 异步读取套接字

Posted

技术标签:

【中文标题】使用 `read` 和 `epoll` 异步读取套接字【英文标题】:Reading a socket asynchronously with `read` and `epoll` 【发布时间】:2019-02-21 15:16:52 【问题描述】:

说到epoll,我有些想念

在 Win32 中,如果在某个 IOCP 下注册了一个套接字并且没有数据可供该套接字读取,则使用 ReadFile 和一些重叠结构发出异步读取操作将返回 false 并且错误代码为 @ 987654324@.

当数据可用时,IOCP 会提取相关的overlapped,给ReadFile 的缓冲区包含新读取的数据,您可以从那里继续。

说到 linux 和 epoll,我不明白。如果您在某个epoll 对象下注册了一个套接字并且没有可用数据,则read 将只返回-1 并且errnoEWOULDBLOCKEAGAIN。我也明白监视EPOLLIN 是半有用的,因为EPOLLIN 谈论的是能够从套接字读取,而不是关于要读取的实际现有数据。

如何告诉套接字“嘿,我想要 X 字节或更少的数据写入这个缓冲区,如果你现在没有数据,那很好 - 当你有的时候给我。通知我什么时候数据存储在缓冲区中”?

epoll 对象是否可以像使用 IOCP 一样?

【问题讨论】:

通知我” - 如何? 等等,你有话题吗?那为什么还要麻烦 epoll 呢?只需进行阻塞读取即可。 EPOLLIN 谈论的是能够从套接字读取,而不是关于要读取的实际现有数据 - EPOLLIN 表示套接字中有数据或错误。 我认为您在非 Windows 操作系统上的工作流程是倒退的。使用epoll(或poll()select()或在BSD上kqueue)查看何时可以成功读取套接字而不会阻塞,然后read()它。如果轮询函数没有表明套接字是可读的,不要费心去尝试。 @melpomene asynchronous-io != io 在另一个线程上。阅读有关 10k 问题的信息。 【参考方案1】:

没有 API 会在 X 数据可用或为您读取缓冲区时通知您。当任何非零数据量可用时,有些 API 会解除阻塞。这些 API 之一是 epoll_wait。您需要自己在缓冲区中读取和收集 X 数据。

【讨论】:

【参考方案2】:

没有 Linux 套接字 API 可以做你想做的事 - 即当套接字可用时执行操作。您将始终必须在代码中显式执行read

您能做的最好的事情是使用poll 多路复用的非阻塞 IO,或者每个套接字有一个线程的阻塞 IO。

【讨论】:

尽管我很欣赏这个答案,但我必须不同意并否认。 IOCP 不能通过在另一个线程上启动操作来工作。否则 IOCP 只是一个蹩脚的线程池。另外,如果您不记得 API 是什么,那么我无法从您的回答中得到任何信息。无论如何谢谢,任何帮助表示赞赏。 @DavidHaim 我的回答中有一个错字 - 它应该是“有 no Linux 套接字 API ...” 抱歉。至于 IOCP 机制,看来我搞错了——我只是将其删除,反正它没有任何用途。

以上是关于使用 `read` 和 `epoll` 异步读取套接字的主要内容,如果未能解决你的问题,请参考以下文章

点对点epoll客户端和死锁

epoll边沿触发漏报消息包问题

Apache select和Nginx epoll模型区别

libcurl 配合epoll 的异步并行server原理

linux 网络编程 ---高级I/O

linux 网络编程 ---高级I/O