一个 IOCP 文档解释问题 - 缓冲区所有权模糊性

Posted

技术标签:

【中文标题】一个 IOCP 文档解释问题 - 缓冲区所有权模糊性【英文标题】:An IOCP documentation interpretation question - buffer ownership ambiguity 【发布时间】:2010-06-12 10:42:55 【问题描述】:

由于我不是以英语为母语的人,我可能会遗漏一些东西,所以也许这里有人比我更了解。

取自 WSASend 在 MSDN 上的文档:

lpBuffers [in]

指向 WSABUF 数组的指针 结构。每个 WSABUF 结构 包含一个指向缓冲区的指针和 缓冲区的长度,以字节为单位。为一个 Winsock 应用程序,一旦 WSASend 函数被调用,系统拥有 这些缓冲区和应用程序可能 不访问它们。这个数组必须 在有效期内保持有效 发送操作。

好的,你能看到粗体字吗?那是不清楚的地方!

我可以想到这行的两种翻译(可能是别的,你说它): 翻译 1 - “buffers”指的是我在调用这个函数时传递的 OVERLAPPED 结构。只有在收到有关它的完成通知时,我才能再次重用该对象。 翻译 2 - “缓冲区”指的是实际缓冲区,即包含我要发送的数据的缓冲区。如果 WSABUF 对象指向一个缓冲区,那么在操作完成之前我不能触摸这个缓冲区。

谁能说出那条线的正确解释是什么?

而且.....如果答案是第二个-您将如何解决? 因为对我来说,这意味着对于我发送的每个数据/缓冲区,我必须在发送方保留一份副本 - 因此在高流量应用程序上有许多“待处理”缓冲区(不同大小),这真的会损害“可扩展性”。

声明 1: 除了上述段落(“And....”)之外,我认为 IOCP 会将要发送的数据复制到它自己的缓冲区并从那里发送,除非您将 SO_SNDBUF 设置为零。

声明 2: 我使用堆栈分配的缓冲区(你知道,函数体中的 char cBuff[1024]; 之类的东西 - 如果主要问题的转换是第二个选项(即缓冲区必须保持原样,直到发送完成),那么......这真是把事情搞砸了!你能想出一个解决办法吗?(我知道,我在上面换句话说)。

【问题讨论】:

【参考方案1】:

答案是在操作完成之前,重叠的结构和数据缓冲区本身不能被重用或释放。

这是因为操作是异步完成的,因此即使数据最终被复制到 TCP/IP 堆栈中操作系统拥有的缓冲区中,这可能要到将来某个时间才会发生,并且您会在写入时收到通知完成发生。请注意,如果您在没有显式流量控制的情况下发送并依赖 TCP 堆栈为您进行流量控制(请参见此处:some OVERLAPS using WSASend not returning in a timely manner using GetQueuedCompletionStatus?),则写入完成可能会延迟惊人的时间...

您不能使用堆栈分配的缓冲区,除非您在重叠结构中放置一个事件并阻塞它直到异步操作完成;这样做并没有什么意义,因为您在正常阻塞调用上增加了复杂性,并且通过发出异步调用然后等待它不会获得很多好处。

在我的 IOCP 服务器框架(您可以从 here 免费获得)中,我使用动态分配的缓冲区,其中包括 OVERLAPPED 结构并且是引用计数的。这意味着清理(在我的情况下,它们被返回到池中以供重用)在完成发生并释放引用时发生。也意味着你可以在操作后选择继续使用缓冲区,清理起来还是很简单的。

参见此处:I/O Completion Port, How to free Per Socket Context and Per I/O Context?

【讨论】:

非常感谢 Len 的回复,从你那里得到它对我来说意义重大!我了解了总体思路,但无法解决具体问题,如 ***.com/questions/3034047/… 所述。 标记为答案,因为您的答案是一天结束时的答案。再次感谢您!

以上是关于一个 IOCP 文档解释问题 - 缓冲区所有权模糊性的主要内容,如果未能解决你的问题,请参考以下文章

Win IOCP下如何识别pushback?

使用 IOCP 的 TCP/IP 服务器。接收缓冲区中的偶尔数据损坏

谁能给我解释一下这个 IOCP 图?

IOCP AcceptEx 在连接时未创建完成

OpenGL es 2.0 三角形上的高斯模糊

WSA 发送到多线程 iocp 服务器中的所有连接的套接字