第3章 TCP協議詳解

第3章 TCP協議詳解


3.1 TCP服務的特色

傳輸協議主要有兩個:TCP協議和UDP協議,TCP協議相對於UDP協議的特色是html

  • 面向鏈接
    使用TCP協議通訊的雙方必須先創建鏈接,完成數據交換後,通訊雙方都必須斷開鏈接以釋放系統資源.算法

  • 字節流

    發送端執行的寫操做次數和接收端執行的讀操做次數之間沒有任何數量關係.

    相比UDP則是發送端每執行一次寫操做,UDP模塊就將其封裝成一個UDP數據報併發送之.爲避免丟包,接收端必須及時針對每個UDP數據報執行讀操做.編程

  • 可靠傳輸

    1) TCP協議採用發送應答機制,即發送端發送的TCP報文都獲得了接收方的應答纔算傳輸成功;

    2) TCP協議採用超時重傳機制,即發送端在發送出一個TCP報文段後啓動定時器,若在定時時間內未收到應答,將會重發該報文.緩存

TCP報文最終是以IP數據報發送的,而IP數據報的特色是無狀態,無鏈接,不可靠的,即接收端可能收到亂序,重複的TCP報文段,因此TCP協議還會對接收到的TCP報文段進行重排與整理,再交付給應用層.服務器


3.2 TCP頭結構

TCP頭部信息出現每個TCP報文段中.markdown

0                   1                   2                   3   
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Sequence Number                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Acknowledgment Number                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Data |           |U|A|P|R|S|F|                               |
| Offset| Reserved  |R|C|S|S|Y|I|            Window             |
|       |           |G|K|H|T|N|N|                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Checksum            |         Urgent Pointer        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options                    |    Padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             data                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • 16位源/目的端口號(Source Port&Destination Port) : 告知主機該報文來自哪裏以及傳給哪一個上層協議或應用程序.查看知名服務可以使用"cat /etc/services"網絡

  • 32位序列號(Sequence Number) : 一次TCP通訊過程當中一個傳輸方向上的字節流的每一個字節的編號.假設主機A和B進行TCP通訊,A發送給B的第一個TCP報文段中,序列值被系統初始化爲某個隨機值ISN(Initial Sequence Number,初始序列號),那麼在該傳輸方向上,後續的TCP報文段中序號值將被系統設置成ISN加上該報文段所攜帶數據的第一個字節在整個字節流中的偏移.併發

  • 32位確認號(Acknowledgment Number) : 用做對另外一方發送來的TCP報文段的響應.其值是收到的TCP報文段的序號加1.app

  • 4位頭部長度(Data Offset) : 即該TCP頭部有多少個32bit字.可見頭部最大長度爲60字節,包括Options部分.ssh

  • 6位標誌位包含以下幾項,能夠爲空

    URG: 表示緊急指針是否有效.

    ACK: 表示確認號是否有效,將擁有此標誌的報文段稱爲確認報文段.

    PSH: 提示接收端應用程序應該當即從TCP接收緩衝區中讀走數據.

    RST: 表示要求對方從新鏈接,將擁有此標誌的報文段稱爲復位報文段.

    SYN: 表示請求一個鏈接,將擁有此標誌的報文段稱爲同步報文段.

    FIN: 表示通知對方本端要關閉鏈接了,將擁有此標誌的報文段稱爲結束報文段.

  • 16位窗口大小(Window) : TCP流量控制的一個手段.這裏的窗口指的是接受通告窗口(Receiver Window,RWND).它告訴對方本端還能容納多少字節的數據,以此對方就能夠控制發送數據的速度.

  • 16位檢碼和(TCP checksum) :由發送端填充,接收端對TCP報文段執行CRC算法以檢驗TCP報文段在傳輸過程當中是否損壞.檢驗內容包括TCP頭部和數據部分.這是TCP可靠傳輸的一個重要保障.

  • 16位緊急指針(Urgent Pointer):其值爲正的偏移量,它是發送端向接收端發送緊急數據的方法.

  • 選項部分(Options) : 是可變長的可選信息.這部分最多可包含40字節. 在這以前的全爲固定部分,佔用20字節的大小.

一.使用tcpdump觀察TCP頭部信息

pi@happyPi:~ $ telnet 127.0.0.1
IP 127.0.0.1.39681 > 127.0.0.1.23: Flags [S], seq 1470116583, win 43690, options [mss 65495,sackOK,TS val 2490119 ecr 0,nop,wscale 7], length 0
0x0000:  4510 003c cde0 4000 4006 6ec9 7f00 0001
0x0010:  7f00 0001 9b01 0017 57a0 32e7 0000 0000
0x0020:  a002 aaaa fe30 0000 0204 ffd7 0402 080a
0x0030:  0025 ff07 0000 0000 0103 0307
  1. 127.0.0.1.39681 > 127.0.0.1.23 表示從127.0.0.1的39681端口 發送至 127.0.0.1的23端口.

  2. Flags [S] 表示該TCP報文段包含SYN標誌,所以是一個同步報文段.

  3. seq 1470116583 ,因爲此報文是這個傳輸方向上第一個TCP報文段,因此這個序列號就是一個ISN.

  4. 因爲是整個通訊過程當中的第一個TCP報文段,因此它沒有針對對方發送來的TCP報文段的確認值.

  5. win 43690 , 表示接受通告窗口的大小,反映的是實際的接受通告窗口大小.

  6. mss(Max Segment Size,MSS) 65495 ,它是通訊雙方協調最大報文段長度,通常會設置爲(MTU-40)字節,40=20(IP頭部)+20(TCP頭部),從而避免發生IP分片,對於以太網來講,MSS值是1460(1500-40)字節.

  7. sackOK : sack(Selective Acknowledgment,選擇性確認)使得TCP模塊只從新發送丟失的TCP報文段,不用發送全部未被確認的TCP報文段.

  8. wscale : wscale(window scale,窗口擴大因子)爲了解決接收通告窗口過小的問題,由於接收窗口大小是用16位表示的,因此最大爲65535(216-1)字節,但實際上TCP模塊容許的接收通告窗口大小遠不止這個數.若wscale爲M,則表示實際接收通告窗口大小爲N * 2M,N爲win的大小.

二.對於TCP頭部的解析:

0x0000:  4510 003c cde0 4000 4006 6ec9 7f00 0001
0x0010:  7f00 0001 9b01 0017 57a0 32e7 0000 0000
0x0020:  a002 aaaa fe30 0000 0204 ffd7 0402 080a
0x0030:  0025 ff07 0000 0000 0103 0307

因爲TCP報文被IP協議封裝過(IP頭部大小爲20字節),因此得從21字節開始看TCP的頭部.

將IP頭部的用"...."替換.

0x0000:  .... .... .... .... .... .... .... ....
0x0010:  .... .... 9b01 0017 57a0 32e7 0000 0000
0x0020:  a002 aaaa fe30 0000 0204 ffd7 0402 080a
0x0030:  0025 ff07 0000 0000 0103 0307
  • 9b01 : 對應源端口號39681.

  • 0017 : 對應目的端口號23.

  • 57a0 32e7 : ‭序號1470116583‬.

  • 0000 0000 : 確認號 0,tcpdump中未顯示.

  • a : 10個32bit,即10*(32/8) = 40字節.

  • 002 : 將其去掉六位保留位,獲得000002,標識碼.

  • aaaa : 窗口大小‭43690‬.

可見TCP報文段頭部的二進制和tcpdumTp輸出的CP報文段描述信息徹底對應.

在後面的分析,將僅顯示序號,確認號,窗口大小以及標誌位等與討論主題有關的字段.


3.3 TCP鏈接的創建和關閉

一. TCP鏈接的創建與三次握手

  1. 源機器對目標機器發起請求(seq:535734930 , Flags[S] , length 0)

  2. 目標機器收到請求,贊成與源機器鏈接,並回復給源機器(seq:2159701207 , Flags[S.] , ack:535734931 , length 0)

  3. 對目標機器回覆的報文的確認(Flags[.] , ack:2159701208 , length 0).

這裏值得注意的是原本seq(序列號)是用來標識TCP數據流中的每個字節的,可是同步報文段比較特殊,即便它並無攜帶任何應用程序數據,它也要佔用一個序列值.

ack爲確認號(Acknowledgment Number) , 其值爲接收到的同步報文段的序列號加1.

以上三個步驟被稱爲TCP的三次握手.

二.TCP鏈接的關閉

  1. 源機器對已創建TCP鏈接的目標機器告之要關閉本鏈接(seq:535734931,ack:2159701208,Flags[F.],length 0)

  2. 目標機器收到通告,併發送確認信息.(ack:535734932 , length 0)

  3. 目標機器發送本身的結束報文段告之要關閉本鏈接(seq:2159701208,ack:535734932,Flags:[F.],length 0)

  4. 源機器發收到通告,併發送確認信息(ack:2159701209 , length 0).

通常而言,TCP鏈接是由客戶端發起的,並經過三次握手創建(特殊狀況是同時打開)的.

而TCP的關閉過程有這麼幾種可能:

  1. 多是客戶端執行主動關閉,好比前面舉的例子.

  2. 多是服務器執行主動關閉,好比服務器程序被中斷而強制關閉鏈接.

  3. 多是同時關閉.

三.TCP鏈接的半關閉狀態

因爲TCP鏈接是全雙工的,因此它容許兩個方向(發送和接收)的數據傳輸被獨立關閉.

於是通訊的一端能夠發送結束報文段給對方,告之本端已完成數據的發送,但容許繼續接收來自對方的數據,直到對方也發送結束報文段以關閉鏈接.

TCP的這種狀態稱之爲半關閉狀態(half close).

四.鏈接超時

對於提供可靠鏈接的TCP來講,在鏈接超時的狀況下必然是先進行重連,若屢次重連仍然無效,則通知應用程序鏈接超時.

因爲HTTP(測試中監聽了80端口)是基於TCP協議的,因此對於如下的測試能夠反映出TCP的重連表現:

pi@happyPi:~ $ sudo tcpdump -n -i eth0 port 80 &
pi@happyPi:~ $ wget www.google.com
11:30:13.695658 IP 192.168.1.108.37366 > 59.24.3.173.80: Flags [S], seq 1964502452, win 29200, options [mss 1460,sackOK,TS val 13783 ecr 0,nop,wscale 7], length 0
11:30:14.692904 IP 192.168.1.108.37366 > 59.24.3.173.80: Flags [S], seq 1964502452, win 29200, options [mss 1460,sackOK,TS val 13883 ecr 0,nop,wscale 7], length 0
11:30:16.692946 IP 192.168.1.108.37366 > 59.24.3.173.80: Flags [S], seq 1964502452, win 29200, options [mss 1460,sackOK,TS val 14083 ecr 0,nop,wscale 7], length 0
11:30:20.702931 IP 192.168.1.108.37366 > 59.24.3.173.80: Flags [S], seq 1964502452, win 29200, options [mss 1460,sackOK,TS val 14484 ecr 0,nop,wscale 7], length 0
11:30:28.722938 IP 192.168.1.108.37366 > 59.24.3.173.80: Flags [S], seq 1964502452, win 29200, options [mss 1460,sackOK,TS val 15286 ecr 0,nop,wscale 7], length 0
11:30:44.742930 IP 192.168.1.108.37366 > 59.24.3.173.80: Flags [S], seq 1964502452, win 29200, options [mss 1460,sackOK,TS val 16888 ecr 0,nop,wscale 7], length 0
11:31:16.822969 IP 192.168.1.108.37366 > 59.24.3.173.80: Flags [S], seq 1964502452, win 29200, options [mss 1460,sackOK,TS val 20096 ecr 0,nop,wscale 7], length 0
failed: Connection timed out.

能夠看到重連的時間間隔爲[1,2,4,8,16,32]s,並且重連了6次數.

關於次數,是由"/proc/sys/net/ipv4/tcp_syn_retries"內核變量來決定的.

pi@happyPi:~ $ cat /proc/sys/net/ipv4/tcp_syn_retries 
6

3.4 TCP狀態鏈接

一.客戶端的狀態

  • 創建鏈接
右邊是狀態名稱且狀態過程是從左到右 SYN_SENT ESTABLISHED
緣由 使用系統調用connect發送一個同步報文段 收到服務器的確認報文段
進一步的操做 回覆給服務端確認報文段
  • 關閉鏈接
右邊是狀態名稱,狀態過程是從左到右 FIN_WAIT_1 FIN_WAIT_2 TIME_WAIT
緣由 向服務器發送結束報文段 收到服務器的確認報文段 收到服務器結束報文段
進一步的操做 回覆給服務端確認接收報文段
備註 FIN_WAIT_1可直接至TIME_WAIT

二.服務端的狀態

  • 創建鏈接
右邊是狀態名稱,狀態過程是從左到右 LISTEN SYN_RCVD ESTABLISHED
緣由 使用系統調用listen監聽請求鏈接 監聽到某個請求鏈接 收到客戶端確認報文段
進一步的操做 回覆給客戶端確認報文段
  • 關閉鏈接
右邊是狀態名稱,狀態過程是從左到右 CLOSE_WAIT LAST_ACK CLOSED
緣由 收到客戶端的結束報文段 發送給客戶端結束報文段 收到客戶端的確認報文段
進一步的操做 回覆給客戶端確認報文段

由以上的過程能夠獲得下面幾個結論:

  1. 對於TCP的鏈接創建,通常來說是客戶端早於服務端,由於服務端的通訊創建完成還得收到客戶端的確認報文段,而此時客戶端已經創建完成.

  2. 處於FIN_WAIT_2狀態的客戶端須要等待服務器發送結束報文段,才能轉移至TIME_WAIT,不然將一直停留在這個狀態.

  3. 在備註裏提過的,FIN_WAIT_1狀態能夠直接進入TIME_WAIT(不通過FIN_WAIT_2),前提是處於FIN_WAIT_1狀態的服務器直接收到帶確認信息的結束報文段(而不是先接收確認報文段,再接收結束報文段).

長時間處於FIN_WAIT_2狀態的鏈接稱之爲孤兒鏈接,Linux爲防止孤兒鏈接長時間留在內核中,定義瞭如下兩個變量,分別指定內核能接管的孤兒鏈接數目與其在內核中生存的時間.

pi@happyPi:~ $ cat /proc/sys/net/ipv4/tcp_max_orphans 
4096
pi@happyPi:~ $ cat /proc/sys/net/ipv4/tcp_fin_timeout 
60

三.TIME_WAIT狀態

在上面客戶端關閉的狀態中有一個是TIME_WAIT,即在客戶端收到服務器的結束報文段以後,並無直接進入CLOSED狀態.

TIME_WAIT有兩個緣由:

  • 可靠的終止TCP鏈接,由於避免回覆給服務器的確認報文段發送失敗.

  • 保證讓遲來的TCP報文段有足夠的時間被識別並丟棄.萬一關閉此端口後被其餘程序使用並收到了原來的數據報.

有時咱們但願避免TIME_WAIT狀態,由於當程序退出後,咱們但願可以當即重啓它.但因爲處在TIME_WAIT狀態的鏈接還佔用着端口,程序將沒法啓動(直到MSL(Maximum Segment Life,報文段最大生存時間)超時時間結束,標準文檔建議的MSL爲2min).

對於客戶端程序來講,一般不用擔憂上面描述的重啓問題,由於它們通常使用系統自動分配的臨時端口號創建鏈接,因爲隨機性,通常會與上次(還處於TIME_WAIT狀態的端口號)使用的不一樣.但若是老是異常終止則說明使用的是一個知名服務端口號.

下圖是在Windows上TCP鏈接的狀態:

活動鏈接

  協議  本地地址          外部地址        狀態
[cloudmusic.exe]
  TCP    192.168.1.106:13355    119.44.11.138:http     ESTABLISHED
 [cloudmusic.exe]
  TCP    192.168.1.106:13359    119.44.11.138:http     ESTABLISHED
 [cloudmusic.exe]
  TCP    192.168.1.106:13360    119.44.11.138:http     ESTABLISHED
 [cloudmusic.exe]
  TCP    192.168.1.106:13362    119.44.18.47:http      LAST_ACK
 [cloudmusic.exe]
  TCP    192.168.1.106:13366    119.44.11.138:http     ESTABLISHED
 [cloudmusic.exe]
  TCP    192.168.1.106:13392    tsa01s08-in-f14:https  LAST_ACK
 [firefox.exe]
  TCP    192.168.1.106:13394    ti-in-f138:http        SYN_SENT
 [firefox.exe]
  TCP    192.168.1.106:13395    ti-in-f101:http        SYN_SENT
 [firefox.exe]
  TCP    192.168.1.106:13396    59.111.160.195:http    LAST_ACK
 [cloudmusic.exe]
  TCP    192.168.1.106:13397    119.44.18.47:http      ESTABLISHED
 [cloudmusic.exe]
  TCP    192.168.1.106:13398    ti-in-f138:http        SYN_SENT
 [firefox.exe]
  TCP    192.168.1.106:13399    ti-in-f101:http        SYN_SENT
 [firefox.exe]

能夠看到這些狀態是能夠在系統中明文標註出來的.進以分析出當前某個程序的鏈接狀態.


3.5 復位報文段

產生復位報文段的三種狀況:

  1. 訪問不存在的端口.

  2. 目標端口仍處於TIME_WAIT狀態.

  3. 處理半打開鏈接.半打開即通訊雙方關閉或者異常終止了鏈接,而未通知對方,並繼續向對方發送數據報.

這在第1種狀況下抓取到的TCP報文段:

pi@happyPi:~ $ sudo tcpdump -nt -i eth0 port 54321 &
pi@happyPi:~ $ telnet  192.168.1.100 54321
Trying 192.168.1.100...
IP 192.168.1.108.48326 > 192.168.1.100.54321: Flags [S], seq 1285841519, win 29200, options [mss 1460,sackOK,TS val 4294956710 ecr 0,nop,wscale 7], length 0
IP 192.168.1.100.54321 > 192.168.1.108.48326: Flags [R.], seq 0, ack 1285841520, win 0, length 0

可見收到了帶Flags[R.]的報文段.


3.6 TCP數據流

本節討論經過TCP鏈接交換的應用程序數據,TCP報文段所攜帶的應用程序數據按照長度分爲兩種:

  • 交互數據

  • 成塊數據

前者對實時性要求高如telnet與ssh等,後者對傳輸效率要求高如ftp等.

一. TCP交互數據流

這種數據流的傳輸方式有一個特色,服務器每次發送的確認報文段都包含它須要發送的應用程序數據.服務器的這種處理方式稱爲延遲確認,即它不立刻確認上次收到的數據,而是在一段延遲時間後查看本端是否還有數據須要發送,如有,則和確認信息一塊兒發出,這樣作的理由是爲了減小發送TCP報文段的數量.

在局域網中交互數據流可能經受很大的延遲,而且,攜帶交互數據的微小TCP報文段數量通常不少(客戶端上一個按鍵就會致使一個TCP報文段),這些因素均可能致使擁塞發生,解決這個問題的一個簡單有效的方法是使用Nagle算法,它會要求一個TCP鏈接的通訊雙方在任意時刻都最多隻能發送一個未被確認的TCP報文段.具體的表如今於,發送方在等待確認的同時,收集本端須要發送的微量數據,並在確認信息到來時以一個TCP報文段將他們所有發出,如此一來就極大的減小了網絡上微小TCP報文段的數量.表面上看來就是"確認到達的越快,數據就發送的越快".

二. TCP成塊數據流

當傳輸大量大塊數據的時候,發送方會連續發送多個TCP報文段(因爲文件太大),可是接收方能夠一次確認這些全部這些報文段.

並且發送方會根據接收方的報文段中接收通告窗口(Window)的大小了解到接收方的接收緩衝區還有多少空閒空間,而且可能會發送一個帶PSH標誌的報文段以通知應用程序儘快讀取數據.

三.帶外(Out Of Band,OOB)數據

帶外數據用於通告對方本端發生的重要事件.所以,帶外數據比普通數據有更高的優先級,它應該是被當即發送,而不管發送緩衝區是否有排隊等待發送的普通數據.而且它可使用一條獨立的傳輸層鏈接,也能夠映射到傳輸普通數據的鏈接中.

UDP/TCP沒有真正的帶外數據,不過TCP利用其頭部中的緊急指針標誌和緊急指針兩個字段,給應用程序提供了一種緊急方式.

TCP接收端只有在接收到緊急指針標誌時候纔會檢查緊急指針,而後根據緊急指針所指的位置肯定帶外數據的位置,並將它讀入一個特殊的緩存中(這個緩存只有1字節,稱爲帶外緩存).若上層應用沒有及時取走帶外緩存中的數據,則後續的帶外數據將覆蓋它.固然,經過設置相關參數,帶外數據也能夠像普通數據同樣被TCP模塊存放在TCP接收緩存區.


3.9 TCP超時重傳

若在創建正常鏈接後忽然網絡情況異常甚至與服務器直接斷開,TCP必須可以重傳超時間內未收到確認的TCP報文段,爲此,TCP模塊爲每一個TCP報文段都維護一個重傳定時器,該定時器在TCP報文段第一次被髮送時啓動.若是超時時間內未收到接收方的應答,TCP模塊將重傳TCP報文段並重置定時器.至於下次重傳的超時時間如何選擇,以及最多執行多少重傳,這就是TCP的重傳策略.

在Linux上有兩個重要內核參數與TCP重傳相關,他們分別是在底層IP接管以前TCP最少執行的重傳次數和鏈接放棄前TCP最多能夠執行的重傳次數.

pi@happyPi:~ $ cat /proc/sys/net/ipv4/tcp_retries1
3 
pi@happyPi:~ $ cat /proc/sys/net/ipv4/tcp_retries2
15

在TCP重傳機制下屢次嘗試失敗的狀況下,將會交給底層的IP和ARP接管,直到所使用的應用程序放棄鏈接爲止.


3.10 擁塞控制

因爲TCP模塊還有一個重要任務,就是提升網絡利用率,下降丟包率,並保證網絡資源對每條數據流的公平性,這就是所謂的擁塞機制.

TCP的擁塞機制有四個部分:

  • 慢啓動(slow start).

  • 擁塞避免(congestion avoidance).

  • 快速重傳(fast retransmit).

  • 快速恢復(fast recovery).

擁塞算法在Linux下有多種實現,好比reno/vegas/cubic算法,在Linux機器上,"/proc/sys/net/ipv4/tcp_congestion_control"中指示了機器當前所使用的擁塞機制控制算法.

pi@happyPi:~ $ cat /proc/sys/net/ipv4/tcp_congestion_control 
cubic

下面介紹在發送數據時起到影響數據發送量的幾個術語:

SWND(Send Window,發送窗口) SMSS(Sender Maximum Segment Size,發送者最大段大小) RWND(Receiver Window,接收窗口) CWND(Congestion Window,擁塞窗口)
發送端向網絡一次連續寫入的數據量 發送者最大段大小,通常等於MSS 接收方可經過其控制發送端的SWND 最終用來控制發送端的SWND,實際值是RWND和CWND的較小者

發送端須要合理的選擇SWND的大小,若是SWND過小,會引發明顯的網絡延遲;反之,若SWND太大,則容易致使網絡擁塞.TCP的擁塞機制最重要的任務就是調整CWND的大小,由於它纔是最終的SWND.

在TCP鏈接創建好以後,CWND會被設置爲初始值IW(Initial Window),其大小爲SMSS的整數倍.
接着爲避免擁塞:

  1. CWND += MIN(N,SMSS).(N爲這次確認中包含的以前未被確認的字節數)    (3.0)
    當CWND大於ssthresh(slow start threshold size,慢啓動門限),進入第2步.

  2. CWND += SMSS * SMSS/CWND.    (3.1)
    使得CWND按照線性方式增加,從而減緩其擴大.

若發生了擁塞,則多是下面兩種狀況引發的:

  • 傳輸超時(TCP重傳定時器溢出).

  • 接收到重複的確認報文段.

如果前者的狀況,則當即重傳並經過以下公式的調整,SWND將小於SMSS,也小於ssthresh,同時再次進入慢啓動階段.

ssthresh = max(FlightSize / 2,2 * SMSS),CWND <= SMSS    (3.2)

如果後者的狀況,按照收到的確認報文段數量不一樣作出相應的反映:

  1. 當收到第3個重複的確認報文段時,就認爲網絡真的發生擁塞了.按照公式(3.2)計算ssthresh,而後當即重傳丟失的報文段,接着設置CWND = ssthresh+3*SMSS.

  2. 每次收到1個重複的確認時,設置CWND += SMSS.

  3. 當收到新數據的確認時,按照公式(3.2)計算ssthresh,接着CWND=ssthresh.

快速重傳和快速恢復完成以後,擁塞控制將恢復到擁塞避免階段,由第三步可得知.

綜合以上的可見關鍵在於根據當前網絡的狀態調整CWND的大小以提升傳輸效率.


關於第3章的總結

這一章從四個部分學習了TCP協議:

  1. TCP頭部信息.主要是通訊的端口指定,TCP鏈接的管理,控制通訊雙方的數據流.

  2. TCP狀態轉移過程.主要是通訊雙方在鏈接到關閉整個過程的狀態變化.

  3. TCP數據流.主要是交互數據流和成塊數據流.

  4. TCP數據流的控制.主要是超時重傳和擁塞控制.

這一章知識點比較多,對TCP的總體有了一個總體的瞭解.它比IP協議具備更強的可操做性.


From

Linux 高性能服務器編程 遊雙著 機械工業出版社

MarkdownPad2

2017/1/21 0:00:09

相關文章
相關標籤/搜索