2

  阅读 MSDN 页面,很明显如果套接字传输层中没有内部缓冲区,Send 将阻塞。这实际上是一件好事,因为我宁愿没有 NoBufferSpaceAvailable 错误。我的理解是传输缓冲区空间很大,但是如果 Send 限制了一些东西以防止这些错误,我很高兴。

但是,尚不清楚还有什么会导致 Send 阻塞。我的猜测是它不会阻塞等待发送的确认,并且发送只会将数据排队到传输缓冲区并返回。 

非常糟糕的是,如果 Send 确实阻塞,直到特定套接字实际上完全阻塞,直到传输完成。如果是这种情况,那么 1000 个中的一个慢速连接可能会减慢整个发送过程。在那种情况下, SendAsync 真的是强制性的。

有人对此有更多详细信息吗?

4

2 回答 2

4

在收到该发送的 ACK 之前,TCP 发送不会阻塞。这就是缓冲的用途。发送是缓冲的,只有在缓冲区满时才会阻塞。同时,TCP 异步地将缓冲区的内容发送给对等方,并在收到 ACK 时将其丢弃。

于 2012-09-10T02:00:54.573 回答
4

正如 EJP 所说,发送缓冲区负责处理任何未确认的数据,也就是说,您发送的任何数据都将保留在缓冲区中,直到被接收方确认为止。这是为了允许稍后重新发送数据,以防数据包的 ACK 永远不会到达。

此外,正如 EJP 所说,每当收到 ACK 时,刚刚确认的数据就会从发送缓冲区中删除,并释放空间,以便您可以将其用于进一步发送。

但是,在发送大量数据并且 ACK 回复缓慢的情况下(由于高延迟、嘈杂的连接或只是在途中断开连接),那么发送缓冲区将被填满并最终导致由于缺少发送缓冲区空间而导致发送阻塞。

因此,未确认的数据本身不会直接导致发送阻塞,但是如果您发送大量数据并且存在网络问题,这意味着 ACK 不会返回给您,那么是的......未确认的数据最终会导致发送阻塞。这是正确的行为。

您不希望在没有收到 ACK 的情况下一直发送数据。如果您确实想要,那么您可能会使用 UDP 而不是 TCP :)

编辑:此外,每个连接使用一个线程并不少见,以避免您提到的特定情况,即一个错误的连接会影响一千个。如果你担心扩展,你可能应该使用异步调用。

于 2012-09-10T02:55:13.087 回答