套接字发送与 sendasync。send 何时真正阻塞?

Har*_*can 3 .net sockets asyncsocket

\xc2\xa0 阅读MSDN页面,很明显,如果套接字传输层中没有内部缓冲区,Send将阻塞。\xc2\xa0 这实际上是一件好事,因为我不想出现NoBufferSpaceAvailable错误。 \xc2\xa0 我的理解是传输缓冲区空间相当大,但如果发送限制以防止这些错误,我很高兴。

\n\n

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

\n\n

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

\n\n

有人有这方面的更多细节吗?

\n

use*_*421 5

TCP 发送不会阻塞等待接收该发送的 ACK。这就是缓冲的目的。发送被缓冲,并且仅在缓冲区已满时阻塞。同时,TCP 异步地将缓冲区的内容发送到对等方,并在收到 ACK 后将其丢弃。

  • 因此,SendAsync 对于程序员来说似乎没有什么价值。然而 ReceiveAsync 确实有很大的价值。具有异步的更高级别的请求-响应模式确实具有价值(纯粹对于响应方)。 (3认同)

Sco*_*rle 5

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

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

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

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

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

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