TCP選項詳解

窗口擴大因子TCP Window Scale Option (WSopt)
1.前言 
TCP窗口縮放選項是用來增加TCP接收窗口的大小而超過65536字節。這個TCP選項以及其他的幾個選項在RFC1323(處理長肥管道網絡,LFN)中定義。 
窗口縮放因子對於BDP大於64KB的時候的數據傳輸的效率非常有用。例如,如果一個T1傳輸鏈路,1.5Mbps是通過衛星的鏈路,RTT時間是513ms,那麼BDP是:1500000*.513 = 769,500位或者96,188字節。最大的64KB窗口僅僅允許填充鏈路緩衝區的68%或者是1.02Mbps。通過使用窗口擴大因子,文件傳輸可以接近 1.5Mbps,而充分利用可用帶寬。這個選現在慢速網絡上發送大於64KB的文件也是有用的。通過使用窗口擴大因子,接收窗口可能增加到最大1GB。 
2.選項格式 
RFC 1323中關於窗口擴大選項的圖示如下: 
       TCP Window Scale Option (WSopt):   Kind: 3 Length: 3 bytes 
                 +---------+---------+-------------+ 
                 | Kind=3 |Length=3 | shift.cnt     | 
                 +---------+---------+-------------+ 
3.工作過程 
①要啓用窗口擴大選項,通訊雙方必須在各自的SYN報文中發送這個選項。主動建立連接的一方在SYN報文中發送這個選項;而被動建立連接的一方只有在收到帶窗口擴大選項的SYN報文之後才能發送這個選項。 


②這個選項只在一個SYN報文中有意義(<SYN>或<SYN,ACK>),包含窗口擴大選項的報文如果沒有SYN位,則會被忽略掉。當連接建立起來後,在每個方向的擴大因子是固定的。注意:在SYN報文本身的窗口字段始終不做任何的擴大(The Window field in a SYN (i.e., a <SYN> or <SYN,ACK>) segment itself is never scaled.)。 


③在啓用窗口擴大選項的情況下,若發送一個窗口通告,要將實際窗口大小右移shift.cnt位,然後賦給TCP首部中的16bit窗口值;而當接收到一個窗口通告時,則將TCP首部中的16bit窗口值左移shift.cnt位,以獲得實際的通告窗口大小。 


④shift.cnt取值範圍爲0~14,即最大TCP序號限定爲2^16 * 2^ 14   = 2^30 < 2^31。該限制用於防止字節序列號溢出。 
SACK選擇確認選項 
1.前言 
TCP通信時,如果發送序列中間某個數據包丟失,TCP會通過重傳最後確認的包開始的後續包,這樣原先已經正確傳輸的包也可能重複發送,急劇降低了TCP性能。爲改善這種情況,發展出SACK(Selective Acknowledgment, 選擇性確認)技術,使TCP只重新發送丟失的包,不用發送後續所有的包,而且提供相應機制使接收方能告訴發送方哪些數據丟失,哪些數據重發了,哪些數 據已經提前收到等。 
2.選項格式 
SACK信息是通過TCP頭的選項部分提供的,信息分兩種,一種標識是否支持SACK,是在TCP握手時發送;另一種是具體的SACK信息。 
SACK允許選項 
       +---------+--------------+ 
       | Kind=4   | Length=2     | 
       +---------+-------------+ 
該選項只允許在有SYN標誌的TCP包中,也即TCP握手的前兩個包中,分別表示各自是否支持SACK。 
SACK選項 




選項長度: 可變,但整個TCP選項長度不超過40字節,實際最多不超過4組邊界值。
                         +--------+--------+
                         | Kind=5 | Length | 
       +--------+--------+--------+-----------------+ 
       |       Left Edge of 1st Block                 | 
       +--------+--------+--------+-----------------+ 
       |       Right Edge of 1st Block               | 
       +--------+--------+--------+-----------------+ 
       |                                             | 
       /       。。。       . . .   。。。。。         / 
       |                                             | 
       +--------+--------+--------+-----------------+ 
       |       Left Edge of nth Block                 | 
       +--------+--------+--------+----------------+ 
       |       Right Edge of nth Block               | 
       +--------+--------+--------+----------------+ 
該選項參數告訴對方已經接收到並緩存的不連續的數據塊,注意都是已經接收的,發送方可根據此信息檢查究竟是哪個塊丟失,從而發送相應的數據塊。 
* Left Edge of Block 
不連續塊的第一個數據的序列號。 
* Right Edge of Block 
不連續塊的最後一個數據的序列號之後的序列號。表示(Left Edge - 1)和(Right Edge)處序列號的數據沒能接收到。 
3.工作過程 
SACK的產生 
SACK通常都是由TCP接收方產生的,在TCP握手時如果接收到對方的SACK允許選項同時自己也支持SACK的話,在接收異常時就可以發送SACK包通知發送方。 


對中間有丟包或延遲時的SACK 
如果TCP接收方接收到非期待序列號的數據塊時,如果該塊的序列號小於期待的序列號,說明是網絡複製或重發的包,可以丟棄;如果收到的數據塊序列號大於期待的序列號,說明中間包被丟棄或延遲,此時可以發送SACK通知發送方出現了網絡丟包。 
爲反映接收方的接收緩存和網絡傳輸情況,SACK中的第一個塊必須描述是那個數據塊激發此SACK選項的,接收方應該儘可能地在SACK選項部分中填寫儘可能多的塊信息,即使空間有限不能全部寫完,SACK選項中要報告最近接收的不連續數據塊,讓發送方能瞭解當前網絡傳輸情況的最新信息。 


對重發包的SACK(D-SACK) 
RFC2883中對SACK進行了擴展,在SACK中描述的是收到的數據段,這些數據段可以是正常的,也可能是重複發送的,SACK字段具有描述重複發送的數據段的能力,在第一塊SACK數據中描述重複接收的不連續數據塊的序列號參數,其他SACK數據則描述其他正常接收到的不連續數據,因此第一塊SACK描述的序列號會比後面的SACK描述的序列號大;而在接收到不完整的數據段的情況下,SACK範圍甚至可能小於當前的ACK值。通過這種方法,發送方可以更仔細判斷出當前網絡的傳輸情況,可以發現數據段被網絡複製、錯誤重傳、ACK丟失引起的重傳、重傳超時等異常的網絡狀況。 


發送方對SACK的響應 
TCP發送方都應該維護一個未確認的重發送數據隊列,數據未被確認前是不能釋放的,這個從重發送隊列中的每個數據塊都有一個標誌位“SACKed”標識是否該塊被SACK過,對於已經被SACK過的塊,在重新發送數據時將被跳過。發送方接收到接收方SACK信息後,根據SACK中數據標誌重發送隊列中相應的數據塊的“SACKed”標誌,但如果接收不到接收方數據,超時後,所有重發送隊列中數據塊的SACKed位都要清除,因爲可能接收方已經出現了異常。 
4.應用舉例 
發送方發送的數據   接收方接收的數據(包括SACK)   接收方發送的ACK 


SACK累加接收的數據 
         5000-5499       (該包丟失)
         5500-5999       5500-5999     5000, SACK=5500-6000 
         6000-6499       6000-6499     5000, SACK=5500-6500 
         6500-6999       6500-6999     5000, SACK=5500-7000 
         7000-7499       7000-7499     5000, SACK=5500-7500 
數據包丟失,ACK丟失 
         3000-3499       3000-3499     3500 (ACK包丟失)
         3500-3999       3500-3999     4000 (ACK包丟失) 
         4000-4499       (該包丟失) 
         4500-4999       4500-4999     4000, SACK=4500-5000 (ACK包丟失) 
         3000-3499       3000-3499     4000, SACK=3000-3500, 4500-5000 
                                               ---------此爲D-SACK 
數據段丟失和延遲 
         500-999         500-999       1000
         1000-1499       (延遲) 
         1500-1999       (該包丟失) 
         2000-2499       2000-2499     1000, SACK=2000-2500 
         1000-2000       1000-1499     1500, SACK=2000-2500 
         1000-2000     2500, SACK=1000-1500 
                                               ---------此爲D-SACK 
數據段丟失且延遲 
         500-999         500-999       1000
         1000-1499       (延遲) 
         1500-1999       (該包丟失) 
         2000-2499       (延遲) 
         2500-2999       (該包丟失) 
         3000-3499       3000-3499     1000, SACK=3000-3500 
         1000-2499       1000-1499     1500, SACK=3000-3500 
         2000-2499     1500, SACK=2000-2500, 3000-3500 
         1000-2499     2500, SACK=1000-1500, 3000-3500 
                                             ---------此爲部分D-SACK 
MSS: Maxitum Segment Size 最大分段大小 
1.前言
最大報文段長度(M S S)表示T C P傳往另一端的最大塊數據的長度。當建立一個連接時,每一方都有用於通告它期望接收的 M S S選項(M S S選項只能出現在S Y N報文段中)。通過MSS,應用數據被分割成TCP認爲最適合發送的數據塊,由TCP傳遞給IP的信息單位稱爲報文段或段(segment)。 
     我們不難聯想到,跟最大報文段長度最爲相關的一個參數是網絡設備接口的MTU,以太網的MTU是1500,基本IP首部長度爲20,TCP首部是20,所以MSS的值可達1460(MSS不包括協議首部,只包含應用數據)。 
2.選項格式   
                 +---------+-----------+-------------+--------+ 
                 | Kind=2 |Length=4     |     Mss值             | 
                 +---------+-----------+-------------+--------+ 


3.工作過程 
     從上面我們可以看到,MSS是可以通過SYN段進行協商的(MSS選項只能出現在SYN報文段中),但它並不是任何條件下都可以協商的,如果一方不接受來自另一方的MSS值(不帶MMS選項即代表不接受),則MSS就定爲默認值536字節。 
     這裏有必要介紹路徑M T U的概念。路徑M T U當前在兩個主機之間的路徑上任何網絡上的最小M T U。路徑M T U的發現可以通過在I P首部中設置“不要分片( D F)”比特,來發現當前路徑上的路由器是否需要對正在發送的 I P數據報進行分片。如果一個待轉發的 I P數據報被設置D F比特,而其長度又超過了 M T U,那麼路由器將返回 I C M P不可達的差錯。 
TCP的路徑MTU發現按如下方式進行: 
①在連接建立時,TCP使用輸出接口或對端聲明的MSS中的最小MTU作爲起始的報文段大小。路徑 MTU發現不允許TCP超過對端聲明的MSS。如果對端沒有指定一個MSS,則默認爲536。 
②一旦選定了起始的報文段大小,在該連接上的所有被 T C P發送的I P數據報都將被設置DF比特。如果某個中間路由器需要對一個設置了 D F標誌的數據報進行分片,它就丟棄這個數據報,併產生一個ICMP的“不能分片”差錯。 
③如果收到這個ICMP差錯,TCP就減少段大小並進行重傳。如果路由器產生的是一個較新的該類ICMP差錯,則報文段大小被設置爲下一跳的 MTU減去IP和TCP的首部長度。如果是一個較舊的該類ICMP差錯,則必須嘗試下一個可能的最小 MTU。當由這個ICMP差錯引起的重傳發生時,擁塞窗口不需要變化,但要啓動慢啓動。 
④由於路由可以動態變化,因此在最後一次減少路徑 M T U的一段時間以後,可以嘗試使用一個較大的值。 
Timestamp時間戳選項
1.前言 
     時間戳選項使發送方在每個報文段中放置一個時間戳值。接收方在確認中返回這個數值,從而允許發送方爲每一個收到的 A C K計算RT T(我們必須說“每一個收到的 A C K”而不是“每一個報文段”,是因爲T C P通常用一個A C K來確認多個報文段)。我們提到過目前許多實現爲每一個窗口只計算一個 RT T,對於包含8個報文段的窗口而言這是正確的。然而,較大的窗口大小則需要進行更好的RT T計算。 
2.選項格式    
+---+-------+--------+-------+-------+-------+--------+------+--------+ 
| Kind=8 | Length=10 |         時間戳           | 時間戳回顯應答         | 
+-----------------------------------+---------------------------------+ 
3.工作過程 
     時間戳是一個單調遞增的值。由於接收方只需要回顯收到的內容,因此不需要關注時間戳單元是什麼。這個選項不需要在兩個主機之間進行任何形式的時鐘同步。 RFC 1323推薦在1毫秒和1秒之間將時間戳的值加1。 
     在連接建立階段,對這個選項的規定與前一節講的窗口擴大選項類似。主動發起連接的一方在它的S Y N中指定選項。只有在它從另一方的 S Y N中收到了這個選項之後,該選項纔會在以後的報文段中進行設置。 
     我們已經看到接收方 T C P不需要對每個包含數據的報文段進行確認,許多實現每兩個報 
文段發送一個A C K。如果接收方發送一個確認了兩個報文段的 A C K,那麼哪一個收到的時間 戳應當放入回顯應答字段中來發回去呢? 
     爲了減少任一端所維持的狀態數量,對於每個連接只保持一個時間戳的數值。選擇何時更新這個數值的算法非常簡單: 
1) TCP跟蹤下一個A C K中將要發送的時間戳的值(一個名爲 t s re c e n t的變量)以及最後發送的A C K中的確認序號(一個名爲l a s t a c k的變量)。這個序號就是接收方期望的序號。 
2)   當一個包含有字節號l a s t a c k的報文段到達時,則該報文段中的時間戳被保存在 t s re c e n t中。 
3)   無論何時發送一個時間戳選項, t s re c e n t就作爲時間戳回顯應答字段被髮送,而序號字段被保存在l a s t a c k中。 




Linux下相關的TCP參數配置 
1. /proc/sys/net/core/rmem_max — 最大的TCP數據接收緩衝 
2. /proc/sys/net/core/wmem_max — 最大的TCP數據發送緩衝 
3. /proc/sys/net/ipv4/tcp_timestamps — 時間戳在(請參考RFC 1323)TCP的包頭增加12個字節 
4. /proc/sys/net/ipv4/tcp_sack — 有選擇的應答 
5. /proc/sys/net/ipv4/tcp_window_scaling — 支持更大的TCP窗口. 
6. /proc/sys/net/core/rmem_default — 默認的接收窗口大小 
7. /proc/sys/net/core/rmem_max — 接收窗口的最大大小 
8. /proc/sys/net/core/wmem_default — 默認的發送窗口大小 

9. /proc/sys/net/core/wmem_max — 發送窗口的最大大小


轉自:http://hi.baidu.com/clusterlee/blog/item/34870719dc53620e34fa4142.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章