2010-06-22 58 views

回答

2

的.Net爲您處理數據的分裂。您可以編寫並接收大於SendBufferSize的包,而不會發現它(如果您不太關心性能)。

1

你的協議中需要一個名爲message framing的東西。有趣的事實:即使發送的信息小於SendBufferSize,您也需要這個。 :)

0

很可能您的數據將在接收時拆分,因此您需要在收到所有數據後重新構建數據。

3

與例如, UDP,TCP不是允許發送單個「消息」的協議,它以相同的形式發送到接收器。您寧願發送和接收字節流。

引擎蓋下,你的數據會分成的IP數據包,無論SendBufferSize,這順便說一句默認爲8192,(比適合單個IP包高得多的值的IP數據包的最大尺寸爲相關MTU,但大部分少於1500字節)。例如:

  1. Socket.Send(2000個字節)
  2. IP分組#1(1460個字節)
  3. IP分組#2(540個字節)

另外:多個Socket.Send()的數據s可能會合並(Nagle's algorithm)。例如:

  1. Socket.Send(1000個字節)
  2. Socket.Send(1000個字節)
  3. IP分組#1(1460個字節)
  4. IP分組#2(540個字節)

接收器無法區分這兩種情況。另外,出於效率原因,在接收端,數據可能會以不同大小的緩衝區傳遞給您。底線:使用TCP,您不能依靠接收的數據包與發送的數據包大小相同並且大小相同。如果您需要,請按照Stephen Cleary的建議添加大小信息,或者使用UDP等協議或者需要可靠性:SCTP。看起來像是過度殺毒,除非你對SCTP對TCP的其他改進感興趣。

4

TCP不是僅限消息的協議。這是一個基於流的協議,負責爲我們分割數據。讓我把你帶到核心部分。在TCP中有兩部分 - 分段和分段。

分段發生在TCP(傳輸層)。這取決於兩個參數 - MSS和窗口大小。 MSS確定設備可以接收的最大段數。 MSS在初始連接建立期間通過TCP選項進行通信。數據流的每個方向都可以使用不同的MSS,操作系統可以確定它。但是,窗口大小由接收方在TCP報頭中發送,以便在等待來自接收主機的確認和窗口更新之前,一次在連接的接收端傳送它可以緩衝的最大數據量。也就是說,主機可以在耗盡接收機窗口大小之前發送多個分段(MSS因子)。

碎片發生在IP(網絡層)兩種方式。如果在發送方和接收方之間的通信路徑上沒有MTU限制的設備,則分段將單獨滿足以太網(1500字節)的MTU。然而,在發送者和接收者之間存在具有MTU限制的中間設備時,IP層(因特網協議)進行數據報分片,使得分組可以形成爲使得它們可以通過具有較小最大傳輸單元的鏈路MTU)比原始數據報大小。在具有MTU限制的中間設備的情況下,發送方還應該部署路徑MTU發現以確定朝向接收方的網絡路徑中的最小MTU,並動態調整MSS以避免網絡內的IP分段。路徑MTU發現是通過在傳出數據包的IP報頭中設置DF(不分片)選項完成的。發送方和接收方之間的通信路徑中的任何MTU小於數據包的通信路徑都會丟棄這些數據包,並用包含該設備MTU的ICMP「Destination Unreachable(Datagram Too Big)」消息回覆發送方。此信息允許發送方適當減少其假定的路徑MTU。

因此,這導致了MSS和MTU之間的關係點。 RFC 791指出:「所有主機必須準備接受高達576個八位字節的數據報(無論它們是全部還是分段)」。因此,IP網絡的最小MTU是576.在TCP的情況下,扣除TCP報頭20個字節和IP報頭20個字節,我們將爲我們提供536個字節作爲TCP的標準MSS。

現在,讓我們進入重新組裝的部分。碎片可能基於中間設備上的MTU發生,但重新組裝只能在目標設備上進行。 TCP負責分段處理,但是在目標設備上,TCP需要負責排序,但是應用程序應該重新組合這些段。因此,如果您只需要基於整個消息的通信並且不需要考慮可靠性,那麼UDP就是您的選擇。但是,請注意,如果您可以通過拆分發送大量數據,則UDP將無法確保數據包的排序,並且無法處理數據包丟失,因爲它不具有重新傳輸等糾錯機制。

如果您想要進行基於消息的通信,就像在UDP中一樣,但要配合TCP功能,如可靠的按序傳送,擁塞控制以及其他改進/功能(如多流,歸屬,內置MTU發現,那麼SCTP應該是您的選擇。但是,如果您的網絡中有傳統的NAT系統,那麼您可能需要在UDP中封裝SCTP。