检索具有多个重叠 I/O 请求的缓冲区

Posted

技术标签:

【中文标题】检索具有多个重叠 I/O 请求的缓冲区【英文标题】:Retrieve buffer with multiple overlapped I/O requests 【发布时间】:2015-06-11 10:42:57 【问题描述】:

关于 Windows 下的重叠 I/O,我想知道一些事情,包括有和没有 I/O 完成端口。 我预先知道使用 WSASend() 后我将收到多少数据包。

所以我想这样做

for (int i = 0; i < n; i++)
   WSARecv(sock, &buffer_array[i], 1, NULL, 0, &overlapped, completion_routine);

我的问题是:在通知缓冲区已填满时,我如何知道哪个缓冲区已被填满?我的意思是,不用猜测调用的顺序(buffer[0]、buffer[1]、buffer[2] 等)。

我会找到一种替代解决方案,例如,在通知时让我的缓冲区指针更干净,并且随着我的应用程序设计的发展更容易更改/适应。

谢谢。

【问题讨论】:

这没什么意义,改用 WSARecvFrom() 吧。 @Hans Passant WSARecvFrom() 并没有什么更快或更有用的方法,相反,它与 IOCP 产生了反作用,因为它有一个线程专门用于从一个地址接收数据包。 【参考方案1】:

现在您正在启动n 并发接收操作。相反,一个接一个地启动它们。上一个完成后开始下一个。

【讨论】:

正是我想填充 n 个缓冲区。我明白你的意思,我的应用程序需要非常面向延迟(比你想象的要多)。由于我在接收后处理每个数据包,因此如果例如我同时接收到 X 个数据包,则一个接一个地使用 WSARecv() 会增加开销。这就是我目前正在做的事情,我的问题是针对能够改变这种行为的。 您使用的是 UDP 吗?那么所有的数据包都是独立且无序的。接收数据包的顺序无关紧要。 它的 UDP 是,但是 UDP 用于网络诊断。在我正在回忆的参数中,有延迟。所以如果你得到我,让你的读数受到开销的影响是很麻烦的,因此我为什么要尽可能地降低它。使用 IOCP 并没有真正的问题,但如果我使用没有 IOCP 的重叠 I/O(只有 1 个接收线程),在处理数据包之前填充缓冲区会更有效。是的,这是微优化,但是将其乘以 1000 会有所收获。 为了简化,让我们留在问题的框架内。基本上我想知道的是 API 是否允许......或者根本不允许。 您需要为每个调用使用不同的重叠结构。无论如何,这是一个要求。即使您不关心订单,代码在这方面也被破坏了。另请注意,您必须处理丢失的数据包。您可能需要取消这些 IO,因为它们会继续闲逛并“捕获”未来的数据包。【参考方案2】:

使用完成例程时,OVERLAPPED 块中的 hEvent 字段未使用,可用于将上下文信息传递给完成例程。通常,这将是指向缓冲区类实例的指针或指向缓冲区实例数组的索引。通常,OVL 块是实例的结构成员,因为每次调用都需要单独的 OVL。

【讨论】:

以上是关于检索具有多个重叠 I/O 请求的缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

win32网络模型之重叠I/O

进程通过内核缓存区请求设备I/O的一些事情

I/O模型分类

I/O模型剖析

分散/聚集IO(scatter/gather)及iovec结构体

Linux系统I/O操作与零拷贝