TCP WSASend 完成标准

Posted

技术标签:

【中文标题】TCP WSASend 完成标准【英文标题】:TCP WSASend Completion Criteria 【发布时间】:2014-01-13 14:01:28 【问题描述】:

我无法找到 TCP WSASend 调用完成意味着什么的规范。 WSASend 操作的完成是否需要收到 ACK 响应?

此问题与 200 毫秒 - 2 秒 ping 超时的较慢网络有关。调用 WSASend 完成回调是否需要 200 毫秒 - 2 秒(或使用任何完成机制)?或者也许只有在某些数据包上,Windows 才会等待 ACK 并认为 WSASend 操作对所有其他数据包完成得更快?

确切的行为对缓冲区生命周期管理有很大影响,进而对性能(锁定、分配/解除分配和引用计数)产生重大影响。

【问题讨论】:

【参考方案1】:

WSASend 不保证以下内容:

    数据已发送(可能已被缓冲) 已收到(可能已丢失) 接收应用程序处理了它(发件人原则上永远不会知道这一点)

它不需要往返。事实上,启用 nagling 后,总是会缓冲 200 毫秒的少量数据,希望应用程序发送更多数据。 WSASend 必须快速返回,这样 nagling 才有机会发挥作用。

如果您需要确认,请更改应用程序协议,以便您得到确认。没有其他办法。

澄清一下,即使没有 nagling (TCP_NODELAY),您的发送操作也不会收到 ACK。它将被发送到网络,但远程端不知道它应该 ACK。 TCP 没有办法说“请立即确认此数据”。正在发送的数据并不意味着它将永远被接收。数据被推到黑洞后一秒钟网络可能会掉线。

【讨论】:

【参考方案2】:

没有记录。它可能会有所不同,具体取决于您是否关闭了发送缓冲。但是,您始终需要注意获得WSASend() 完成所需的潜在时间,尤其是在您使用异步调用的情况下。详情请见this article of mine。

当 TCP 堆栈用完你的缓冲区时,你会得到一个 WSASend() 完成。如果您没有通过将SO_SNDBUF 设置为零来关闭发送缓冲,那么这可能意味着一旦堆栈将您的数据复制到其缓冲区中,您将获得完成。如果您关闭了发送缓冲,那么这可能意味着一旦您收到 ACK,您将获得完成(仅仅是因为堆栈应该需要您的缓冲区来进行任何潜在的重新传输)。但是,它没有记录在案。

【讨论】:

您认为TCP_NODELAY 会有所作为吗? 这可能意味着数据的发送速度会略微加快,因此可能会略微减少完成时间。

以上是关于TCP WSASend 完成标准的主要内容,如果未能解决你的问题,请参考以下文章

具有多个缓冲区的 WSASend() - 可以完成不完整吗?

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

如何知道完成数据包是针对 WSASend() 还是 WSARecv() 还是 AcceptEx()?

IOCP:内核如何决定同步或异步完成 WSASend?

阻塞模式下的 WSASend() 是不是会导致将通知数据包放置在完成端口中?

readv()、writev()、WSARecv()、WSASend()