2012-09-09 30 views
2

阅读MSDN页面,很明显,如果套接字传输层中没有内部缓冲区,发送将会阻塞。这实际上是一件好事,因为我宁愿没有NoBufferSpaceAvailable错误。我的理解是传输缓冲区空间很大,但如果发送节流阀来防止这些错误,我很高兴。套接字发送与sendasync。什么时候发送实际阻止?

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

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

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

+0

如果您等待异步套接字返回某些内容(即:结果),它也会阻塞。 – DarthVader

回答

4

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

此外,正如EJP所说,无论何时接收到ACK,刚刚确认的数据都将从发送缓冲区中移除,并且空间释放,因此您可以将其用于进一步发送。

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

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

你不想永远发送数据,没有收到ACK。如果你真的想这样做,那么你可能会使用UDP而不是TCP:)

编辑:此外,每个连接使用一个线程,以避免具体情况你提到一个不良连接可以影响一个千。如果你担心缩放,你可能应该使用异步调用。

+1

如果接收方没有跟上发送方,发送缓冲区也可能会因为耗尽滑动窗口而被填满。 – EJP

+0

谢谢。猜猜我会移动开始发送或sendasync然后。还没有看到任何阻止与发送,但它一定会发生,我不希望它阻止我的发送线程,或每发送一个线程。干杯。 –

4

TCP发送不会阻塞,直到接收到该发送的ACK。这就是缓冲的目的。发送被缓存,并且只在缓冲区满时阻塞。与此同时,TCP正在将缓冲区的内容发送给对等方,并在被确认时将其丢弃。

+2

因此,似乎SendAsync对程序员没什么价值。 ReceiveAsync确实有很多价值。更高级别的请求 - 响应模式与异步确实有价值(纯粹用于响应端)。 – Todd