套接字发送vs sendasync。什么时候发送实际阻止?

时间:2012-09-09 23:34:12

标签: .net sockets asyncsocket

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

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

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

任何人都有关于此的更多细节吗?

2 个答案:

答案 0 :(得分:4)

在收到该发送的ACK之前,TCP发送不会阻塞。这就是缓冲的目的。发送缓冲,缓冲区已满时仅阻塞。同时,异步,TCP正在将缓冲区的内容发送给对等方,并在确认时丢弃它们。

答案 1 :(得分:4)

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

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

然而,在发送大量数据的情况下,并且ACK很慢(由于高延迟,嘈杂的连接或沿途的断开连接),然后发送缓冲区将被填满并将由于缺少发送缓冲区空间,最终会导致发送阻塞。

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

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

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