我应该处理 WSASend() 可能不会发送所有数据的事实吗?

Posted

技术标签:

【中文标题】我应该处理 WSASend() 可能不会发送所有数据的事实吗?【英文标题】:Should I handle the fact that WSASend() may not send all data? 【发布时间】:2015-02-27 21:52:13 【问题描述】:

我发现WSASend()可能不会发送所有数据,例如如果我要求它发送800字节,它可能只发送600字节。

现在我的问题是:发生这种情况的情况是否极为罕见,我不应该费心处理此类事件。还是我必须处理它?例如,我不能向用户显示一条错误消息,即并非所有数据都已发送并中止连接而不是尝试恢复吗?

注意:我正在使用 IOCP。

【问题讨论】:

【参考方案1】:

使用重叠 I/O 和 IOCP 发送时,您不太可能看到部分发送。您可能更有可能看到一个带有错误的发送,您想发送系统页面大小的倍数并且只发送了一个较小的倍数,但即使这样也不太可能(而且我没有强制的单元测试我认为这种情况是理论上的)。

当通过重叠 I/O 通过 TCP 连接发送时,当您的对等方接收和处理的速度比您发送的慢时,this 是您更可能遇到的情况,即 TCP 流控制启动in 和您的 WSASend() 呼叫需要越来越长的时间才能完成。

您实际上不太可能从WSASend() 调用或随后的GetQueuedCompletionStatus() 调用中看到错误。事情会继续工作,直到他们不...

【讨论】:

那么,如果我不尝试从部分发送中恢复是否可以,也许正如我所说的,只是显示一条错误消息并中止连接? 如果您有多个未决的发送并且您收到部分发送失败,则可能无法执行任何其他操作,因为如果发送 #6 部分失败但 #7 和#8 完成 OK。【参考方案2】:

只要接收者比发送者慢,它就可能发生。您必须通过重新安排要写入的剩余数据来处理它。不要将其视为错误。

【讨论】:

实际上,如果您使用 IOCP 并且发送重叠,则这种情况极不可能发生。 如果你不同意,我真的很想有一个单元测试来处理这个问题,所以一个可重现的场景会很棒。 @LenHolgate 这里需要一个规范性参考,说明您的链接状态,IOCP 在发送所有数据之前不会完成。如果没有我会坚持我的回答。例如,Posix 标准提供了阻塞模式。 虽然我同意这很好,但您是否经历过您所描述的场景?与 IOCP 合作 15 年以来,我从未见过这种情况。另外,我完全不同意您答案中“任何时候接收器变慢”的部分,因为这意味着这是一种常见情况,而事实并非如此。当接收者变慢时,实际发生的是发送者只是使用资源。至少在现代操作系统上,发送者可以继续发送,直到耗尽非分页池。此外,您假设您可以重新安排发送 - 多个待处理的发送可能是不可能的。

以上是关于我应该处理 WSASend() 可能不会发送所有数据的事实吗?的主要内容,如果未能解决你的问题,请参考以下文章

在我使用完服务后,我应该处理服务(层)类吗?

我应该处理 X509Certificate2 吗?

我应该处理超过 MAX_PATH 的文件吗?

第二次创建peerconeection WebRTC时出现问题(轨道已经存在一个发件人。),我应该处理任何想法

是否有可能不会收到 WSASend 调用的完成?

服务器或客户端在发送/接收日期时应该处理时区吗?