2017-04-13 104 views
2

這是我的理解,如果寫入的數據量很小,寫入TCP/IP套接字將是原子。原子,我的意思是接收器將接收所有的數據或不接收數據。但是,如果寫入的數據量很大,則不是原子的。我對麼?如果是這樣,什麼重要?TCP/IP套接字是否原子?

感謝, 鮑勃

+1

鮑勃,你的問題很好,許多程序員有錯誤,他們認爲如果他們在TCP套接字中發送N個字節,另一個節點將讀取全部N個字節。然後,他們運行功能測試並開始工作。但是,這是一個在某個時刻會在系統中產生故障的錯誤。你想要做的是創建一個簡單的應用層協議,通常是TLV(Type,Length,Value)。我在這裏解釋它(這個問題適用於任何編程語言):http://stackoverflow.com/questions/19839172/how-to-read-all-of-inputstream-in-server-socket-java/19863726#19863726 – rodolk

回答

1

對於UDP,這是真的,因爲應用程序寫入的所有數據在一個UDP數據包發送出去。

對於TCP,事實並非如此,除非應用程序一次只發送1個字節的數據。寫入TCP套接字會將所有數據寫入與該套接字關聯的緩衝區。然後,TCP將在後臺從該緩衝區讀取數據並將其發送到接收器。多少數據TCP實際上發送在一個TCP段取決於其流控制機制的變量和其它因素,包括:

  • ,接收所述其它節點(接收器)公佈的窗口數據的
  • 金額先前發送在飛行段還未被確認
  • 慢啓動和擁塞避免算法狀態
  • 協商的最大段大小(MSS)

在TCP,你永遠無法assum e應用程序寫入套接字的內容實際上是由接收器讀取的。套接字緩衝區中的數據可以在一個或多個TCP段中發送到接收器。在數據可用的任何時刻,接收者可以執行套接字讀取並返回當前實際可用的任何數據。

當然,所有發送的數據最終都會到達接收方,如果中間沒有故障阻止,並且接收方在數據到達之前沒有關閉連接或停止讀取。

+1

「*,除非應用程序一次只發送1個字節的數據*」 - 即使這不是保證,因爲數據默認被緩衝。除非啓用'TCP_NODELAY'套接字選項,否則可以執行多個1字節寫入操作,並仍然將它們一起發送到單個TCP段中。 –

+1

而且無論如何,您仍然可以*在一次接收操作中*接收*它們。 @RemyLebeau – EJP

+0

@EJP:是的,如果在應用程序執行新的讀取操作之前接收並緩衝了套接字中的多個TCP段。 –

2

No. TCP是一種字節流協議。沒有消息,沒有類似數據報的行爲。

+0

根據我收到的響應,如果服務器寫入一個四字節整數並且客戶端讀取一個四字節整數,則讀取可能只返回兩個字節,因爲寫入不是原子的,隨後的讀取將返回另外兩個字節。我有這個權利嗎?鮑勃。 – Bob

+0

@鮑勃,這是正確的。 – rodolk