具有多个缓冲区的 WSASend() - 可以完成不完整吗?
Posted
技术标签:
【中文标题】具有多个缓冲区的 WSASend() - 可以完成不完整吗?【英文标题】:WSASend() with more than one buffer - could complete incomplete? 【发布时间】:2010-06-16 22:01:38 【问题描述】:假设我发布了以下 WSASend 调用(没有回调函数的 Windows I/O 完成端口):
void send_data()
WSABUF wsaBuff[2];
wsaBuff[0].len = 20;
wsaBuff[1].len = 25;
WSASend(sock, &wsaBuff[0], 2, ......);
当我从完成端口收到“write_done”通知时,是否有可能 wsaBuff[1] 将被完全发送(25 个字节)而 wsaBuff[0] 将仅部分发送(例如 7 个字节)?
【问题讨论】:
【参考方案1】:正如我之前所说,在回复您的其他一个非常相似的问题时,唯一可能失败的情况是在资源不足的情况下(最有可能出现非分页池或锁定页面限制问题),您可能会部分完成并返回 ENOBUFS 错误。再说一次,正如我之前所说,在 10 年的 IOCP 开发工作中,我从未将其视为生产中的问题,仅在我们一直在对系统进行压力测试至死的情况下(实际上有时是非分页池耗尽有时会导致行为不端的驱动程序蓝屏框)。
我建议你简单地添加一些代码来记录失败,关闭套接字,就是这样,你已经处理了失败的可能性,可以继续前进。如果您的故障处理代码曾经被执行过,我会感到惊讶。但是您可以确信您会知道它是否存在,并且一旦您可以重现该问题,您就可以花更多时间考虑是否真的需要更好地处理它。
【讨论】:
你确定莱恩吗?仔细注意这个特定的问题 - 它是一个 WSASend() 调用而不是几个,因此我希望它将 WSABUF 数组视为一个单一的、连续的缓冲区......这就是我的问题实际上是关于。 如果您将套接字的发送缓冲区大小设置为零,那么您的缓冲区将被锁定在内存中,因此如果超过锁定的页面限制,可能会导致 ENOBUFS 返回,同样我们都不知道这种情况下的确切非分页池使用情况。您使用分散/收集 I/O 的事实并不重要,恕我直言,实际上是相关的。此外,由于 WSASend() 的文档没有说这种情况不会导致您所询问的错误,您必须假设它可以发生,因此,恕我直言,我的答案是有效的。【参考方案2】:由于WSASend
是进行重叠套接字 IO 的首选方式,因此如果它在不完整的情况下完成将没有任何意义 - 完成通知/例程/事件是应用程序清理/回收使用的结构的唯一方法.
另外:不,这是不可能的,单个 WSASend
调用仍然是单个 IO 调用,无论使用什么缓冲区。
【讨论】:
以上是关于具有多个缓冲区的 WSASend() - 可以完成不完整吗?的主要内容,如果未能解决你的问题,请参考以下文章
如何避免使用函数调用 WSAsend 将多个缓冲区组合成一个 UDP 数据包?
在重叠模式下使用 WSASend 时,我应该何时释放缓冲区?
io 完成端口问题,每个 GetQueuedCompletionStatus 调用多个 wsarecv 或 wsasend