使用 `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
并且errno
是EWOULDBLOCK
或EAGAIN
。我也明白监视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` 异步读取套接字的主要内容,如果未能解决你的问题,请参考以下文章