2012-09-09 33 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