使用套接字时,哪些 IO 操作会导致完成数据包发送到完成端口?

Posted

技术标签:

【中文标题】使用套接字时,哪些 IO 操作会导致完成数据包发送到完成端口?【英文标题】:What IO operations causes completion packets to be sent to the completion port when using sockets? 【发布时间】:2015-03-11 07:38:35 【问题描述】:

在IOCP中,当启动一个IO操作如WSARecv()时,当IO操作完成时,会向完成端口发送一个完成包。

我想知道的是什么IO操作导致使用sockets时完成包被发送到完成端口,比如我知道WSASend(),WSARecv(),AcceptEx(),PostQueuedCompletionStatus()导致完成要发送的数据包。是否还有其他 IO 操作可以做到这一点?

【问题讨论】:

【参考方案1】:

仅当以请求完成排队的方式调用可生成完成的 API 调用时,完成才会排队到与套接字关联的 IOCP。因此,您将通过阅读文档并将OVERLAPPED 结构传递给它们来知道哪些API 调用可以生成完成。

因此,您实际上并不需要知道问题的答案,因为您永远不会获得您不希望获得的完成,因为您必须调用具有适当参数的适当 API 才能生成完成。

然后,您可以通过将某种形式的标识“每个操作数据”添加到 OVERLAPPED 来区分导致生成完成的 API,方法是制作“扩展重叠结构”或使用事件句柄作为不透明数据。无论哪种方式,您都有机会将一些上下文从 API 调用站点发送到 IOCP 完成处理站点。这个上下文是你自己设计的,可以告诉你是什么启动了完成。

然后您可以使用来自GetQueuedCompletionStatus() 调用的返回值来确定完成是成功还是失败,然后您可以使用WSAGetLastError() 访问失败的错误代码(尽管see this answer 了解更多关于一个额外的圈,您可以跳过它以获得更准确的错误代码)。

然后,您可以确定您拥有 EJP 答案中列出的哪些事件。

可以为套接字操作生成完成的实际函数集可能会随着操作系统的变化而变化。确定这些对于您所针对的操作系统而言是什么的最简单方法是阅读 MSDN 文档或搜索 SDK 标头以查找 lpOverlapped...正如您从当前的 VS2013 标头中看到的那样有很多与套接字有关的; AcceptEx()ConnectEx()DisconnectEx()TransmitFile()、HTTP.sys API、RIO API等

【讨论】:

【参考方案2】:

你没有抓住重点。导致发送完成数据包的原因是 事件, 而不是 API 调用。基本上只有几个 TCP 事件:

入站连接 出站连接完成 数据 写完 超时 流结束,并且 错误。

【讨论】:

【参考方案3】:

复制自site

支持的 I/O 功能

以下函数可用于启动通过使用 I/O 完成端口完成的 I/O 操作。您必须向函数传递一个 OVERLAPPED 结构的实例和一个先前与 I/O 完成端口关联的文件句柄(通过调用 CreateIoCompletionPort)来启用 I/O

完成端口机制:

    连接命名管道 DeviceIoControl Lo​​ckFileEx ReadDirectoryChangesW 读取文件 TransactNamedPipe WaitCommEvent 写文件 WSASendMsg WSASendTo WSASend WSARecvFrom WSARecvMsg WSARecv

【讨论】:

以上是关于使用套接字时,哪些 IO 操作会导致完成数据包发送到完成端口?的主要内容,如果未能解决你的问题,请参考以下文章

发送后如何正确关闭套接字(使用 IOCP)?

socket.io 由于数据大小而断开连接

通过 posix 套接字发送文件时的零窗口

套接字编程,如果我写入的数据超过一个 TCP/UDP 数据包可以携带会怎样?

使用数据包套接字在同一网络接口上发送和接收时无法接收包

7.3 5种IO模型与IO复用