TCP協(xié)議詳解
一、TCP協(xié)議
1、TCP 通過以下方式提供可靠性:
· ◆ 應(yīng)用程序分割為TCP認(rèn)為最合適發(fā)送的數(shù)據(jù)塊。由TCP傳遞給IP的信息單位叫做報文段。
· ◆ 當(dāng)TCP發(fā)出一個報文段后,它啟動一個定時器,等待目的端確認(rèn)收到這個報文段。如果不能記時收到一個確認(rèn),它 就重發(fā)這個報文段。
· ◆ 當(dāng)TCP收到發(fā)自TCP連接另一端的數(shù)據(jù),它將發(fā)送一個確認(rèn)。這個確認(rèn)不是立即發(fā)送,通常延遲幾分之一秒。
· ◆ TCP將保持它首部和數(shù)據(jù)的檢驗和。這是一個端到端的檢驗和,目的是檢測數(shù)據(jù)在傳輸過程中的任何變化如果收到報文段的檢驗和有差錯,TCP將丟棄這個報文段和不確認(rèn)收到這個報文段。
· ◆ 既然TCP報文段作為IP數(shù)據(jù)報來傳輸,而IP數(shù)據(jù)報的到達可能失序,因此TCP報文段的到達也可能失序。如果必要,TCP將對收到的數(shù)據(jù)進行排序,將收到的數(shù)據(jù)以正確的順序交給應(yīng)用層。
· ◆ 既然IP數(shù)據(jù)報會發(fā)生重復(fù),TCP連接端必須丟棄重復(fù)的數(shù)據(jù)。
· ◆ TCP還能提供流量控制,TCP連接的每一方都有固定大小的緩沖空間。TCP的接收端只允許另一端發(fā)送接收端緩沖區(qū)所能接納的數(shù)據(jù)。這將防止較快主機致使較慢主機的緩沖區(qū)溢出。
另外,TCP對字節(jié)流的內(nèi)容不作任何解釋。
2、TCP首部:
TCP數(shù)據(jù)被封裝在一個IP數(shù)據(jù)報中,格式如下:
IP首部20 | TCP首部20 | TCP首部 |
TCP首部格式如下:
16位源端口號 | 16位目的端口號 | |||||||
32位序號 | ||||||||
32位確認(rèn)序號 | ||||||||
4位首部長度 | 保留6位 | U | A | P | R | S | F | 16位窗口大小 |
16位檢驗和 | 16位緊急指針 | |||||||
選項 | ||||||||
數(shù)據(jù) | ||||||||
說明:
(1)每個TCP段都包括源端和目的端的端口號,用于尋找發(fā)送端和接收端的應(yīng)用進程。這兩個值加上IP首部的源端IP地址和目的端IP地址唯一確定一個TCP連接。
(2)序號用來標(biāo)識從TCP發(fā)送端向接收端發(fā)送的數(shù)據(jù)字節(jié)流,它表示在這個報文段中的第一個數(shù)據(jù)字節(jié)。如果將字節(jié)流看作在兩個應(yīng)用程序間的單向流動,則TCP用序號對每個字節(jié)進行計數(shù)。
(3)當(dāng)建立一個新連接時,SYN標(biāo)志變1。序號字段包含由這個主機選擇的該連接的初始序號ISN,該主機要發(fā)送數(shù)據(jù)的第一個字節(jié)的序號為這個ISN加1,因為SYN標(biāo)志使用了一個序號。
(4)既然每個被傳輸?shù)淖止?jié)都被計數(shù),確認(rèn)序號包含發(fā)送確認(rèn)的一端所期望收到的下一個序號。因此,確認(rèn)序號應(yīng)當(dāng)時上次已成功收到數(shù)據(jù)字節(jié)序號加1。只有ACK標(biāo)志為1時確認(rèn)序號字段才有效。
(5)發(fā)送ACK無需任何代價,因為32位的確認(rèn)序號字段和ACK標(biāo)志一樣,總是TCP首部的一部分。因此一旦一個連接建立起來,這個字段總是被設(shè)置,ACK標(biāo)志也總是被設(shè)置為1。
(6)TCP為應(yīng)用層提供全雙工的服務(wù)。因此,連接的每一端必須保持每個方向上的傳輸數(shù)據(jù)序號。
(7)TCP可以表述為一個沒有選擇確認(rèn)或否認(rèn)的華東窗口協(xié)議。因此TCP首部中的確認(rèn)序號表示發(fā)送方已成功收到字節(jié),但還不包含確認(rèn)序號所指的字節(jié)。當(dāng)前還無法對數(shù)據(jù)流中選定的部分進行確認(rèn)。
(8)首部長度需要設(shè)置,因為任選字段的長度是可變的。TCP首部最多60個字節(jié)。
(9)6個標(biāo)志位中的多個可同時設(shè)置為1
◆ URG-緊急指針有效
◆ ACK-確認(rèn)序號有效
◆ PSH-接收方應(yīng)盡快將這個報文段交給應(yīng)用層
◆ RST-重建連接
◆ SYN-同步序號用來發(fā)起一個連接
◆ FIN-發(fā)送端完成發(fā)送任務(wù)
(10)TCP的流量控制由連接的每一端通過聲明的窗口大小來提供。窗口大小為字節(jié)數(shù),起始于確認(rèn)序號字段指明的值,這個值是接收端期望接收的字節(jié)數(shù)。窗口大小是一個16為的字段,因而窗口大小最大為65535字節(jié)。
(11)檢驗和覆蓋整個TCP報文端:TCP首部和TCP數(shù)據(jù)。這是一個強制性的字段,一定是由發(fā)送端計算和存儲,并由接收端進行驗證。TCP檢驗和的計算和UDP首部檢驗和的計算一樣,也使用偽首部。
(12)緊急指針是一個正的偏移量,黃蓉序號字段中的值相加表示緊急數(shù)據(jù)最后一個字節(jié)的序號。TCP的緊急方式是發(fā)送端向另一端發(fā)送緊急數(shù)據(jù)的一種方式。
(13)最常見的可選字段是最長報文大小MMS,每個連接方通常都在通信的第一個報文段中指明這個選項。它指明本端所能接收的最大長度的報文段。
二、TCP連接的建立和終止
1、建立連接協(xié)議
(1) 請求端發(fā)送一個SYN段指明客戶打算連接的服務(wù)器的端口,隱疾初始序號(ISN),這個SYN報文段為報文段1。
(2) 服務(wù)器端發(fā)回包含服務(wù)器的初始序號的SYN報文段(報文段2)作為應(yīng)答。同時將確認(rèn)序號設(shè)置為客戶的ISN加1以對客戶的SYN報文段進行確認(rèn)。一個SYN將占用一個序號。
(3) 客戶必須將確認(rèn)序號設(shè)置為服務(wù)器的ISN加1以對服務(wù)器的SYN報文段進行確認(rèn)(報文段3)。
這3個報文段完成連接的建立,稱為三次握手。發(fā)送第一個SYN的一端將執(zhí)行主動打開,接收這個SYN并發(fā)回下一個SYN的另一端執(zhí)行被動打開。
2、連接終止協(xié)議
由于TCP連接是全雙工的,因此每個方向都必須單獨進行關(guān)閉。這原則是當(dāng)一方完成它的數(shù)據(jù)發(fā)送任務(wù)后就能發(fā)送一個FIN來終止這個方向的連接。收到一個FIN只意味著這一方向上沒有數(shù)據(jù)流動,一個TCP連接在收到一個FIN后仍能發(fā)送數(shù)據(jù)。首先進行關(guān)閉的一方將執(zhí)行主動關(guān)閉,而另一方執(zhí)行被動關(guān)閉。
?。?/span>1) TCP客戶端發(fā)送一個FIN,用來關(guān)閉客戶到服務(wù)器的數(shù)據(jù)傳送(報文段4)。
?。?/span>2) 服務(wù)器收到這個FIN,它發(fā)回一個ACK,確認(rèn)序號為收到的序號加1(報文段5)。和SYN一樣,一個FIN將占用一個序號。
?。?/span>3) 服務(wù)器關(guān)閉客戶端的連接,發(fā)送一個FIN給客戶端(報文段6)。
?。?/span>4) 客戶段發(fā)回確認(rèn),并將確認(rèn)序號設(shè)置為收到序號加1(報文段7)。
3、連接建立的超時
如果與服務(wù)器無法建立連接,客戶端就會三次向服務(wù)器發(fā)送連接請求。在規(guī)定的時間內(nèi)服務(wù)器未應(yīng)答,則連接失敗。
4、最大報文段長度MSS
最大報文段長度表示TCP傳往另一端的最大塊數(shù)據(jù)的長度。當(dāng)一個連接建立時,連接的雙方都要通告各自的MSS。
一般,如果沒有分段發(fā)生,MSS還是越大越好。報文段越大允許每個報文段傳送的數(shù)據(jù)越多,相對IP和TCP首部有更高的網(wǎng)絡(luò)利用率。當(dāng)TCP發(fā)送一個SYN時,它能將MSS值設(shè)置為外出接口的MTU長度減去IP首部和TCP首部長度。對于以太網(wǎng),MSS值可達1460。
如果目的地址為非本地的,MSS值通常默認(rèn)為536,是否本地主要通過網(wǎng)絡(luò)號區(qū)分。MSS讓主機限制另一端發(fā)送數(shù)據(jù)報的長度,加上主機也能控制它發(fā)送數(shù)據(jù)報的長度,這將使以較小MTU連接到一個網(wǎng)絡(luò)上的主機避免分段。
5、 TCP的半關(guān)閉
TCP提供了連接的一端在結(jié)束它的發(fā)送后還能接收來自另一端數(shù)據(jù)的能力,這就是TCP的半關(guān)閉。
客戶端發(fā)送FIN,另一端發(fā)送對這個FIN的ACK報文段。當(dāng)收到半關(guān)閉的一端在完成它的數(shù)據(jù)傳送后,才發(fā)送FIN關(guān)閉這個方向的連接,客戶端再對這個FIN確認(rèn),這個連接才徹底關(guān)閉。
6、2MSL連接
TIME_WAIT狀態(tài)也稱為2MSL等待狀態(tài)。每個TCP必須選擇一個報文段最大生存時間(MSL)。它是任何報文段被丟棄前在網(wǎng)絡(luò)的最長時間。
處理原則:當(dāng)TCP執(zhí)行一個主動關(guān)閉,并發(fā)回最后一個ACK,該連接必須在TIME_WAIT狀態(tài)停留的時間為2MSL。這樣可以讓TCP再次發(fā)送最后的ACK以避免這個ACK丟失(另一端超時并重發(fā)最后的FIN)。這種2MSL等待的另一個結(jié)果是這個TCP連接在2MSL等待期間,定義這個連接的插口不能被使用。
7、平靜時間
TCP在重啟的MSL秒內(nèi)不能建立任何連接,這就是平靜時間。
8、FIN_WAIT_2狀態(tài)
在FIN_WAIT_2狀態(tài)我們已經(jīng)發(fā)出了FIN,并且另一端也對它進行了確認(rèn)。只有另一端的進程完成了這個關(guān)閉,我們這端才會從FIN_WAIT_2狀態(tài)進入TIME_WAIT狀態(tài)。這意味著我們這端可能永遠(yuǎn)保持這個狀態(tài),另一端也將處于CLOSE_WAIT狀態(tài),并一直保持這個狀態(tài)直到應(yīng)用層決定進行關(guān)閉。
9、復(fù)位報文段
TCP首部的RST位是用于復(fù)位的。一般,無論合適一個報文端發(fā)往相關(guān)的連接出現(xiàn)錯誤,TCP都會發(fā)出一個復(fù)位報文段。主要情況:
(1)到不存在的端口的連接請求;
(2)異常終止一個連接。
10、同時打開
為了處理同時打開,對于同時打開它僅建立一條連接而不是兩條連接。兩端幾乎在同時發(fā)送SYN,并進入SYN_SENT狀態(tài)。當(dāng)每一端收到SYN時,狀態(tài)變?yōu)?/span>SYN_RCVD,同時他們都再發(fā)SYN并對收到的SYN進行確認(rèn)。當(dāng)雙方都收到SYN及相應(yīng)的ACK時,狀態(tài)都變?yōu)?/span>ESTABLISHED。一個同時打開的連接需要交換4個報文段,比正常的三次握手多了一次。
11、 同時關(guān)閉
當(dāng)應(yīng)用層發(fā)出關(guān)閉命令,兩端均從ESTABLISHED變?yōu)?/span>FIN_WAIT_1。這將導(dǎo)致雙方各發(fā)送一個FIN,兩個FIN經(jīng)過網(wǎng)絡(luò)傳送后分別到達另一端。收到FIN后,狀態(tài)由FIN_WAIT_1變?yōu)?/span>CLOSING,并發(fā)送最后的ACK。當(dāng)收到最后的ACK,狀態(tài)變?yōu)?/span>TIME_WAIT。同時關(guān)閉和正常關(guān)閉的段減緩數(shù)目相同。
12、TCP選項
每個選項的開始是1字節(jié)的kind字段,說明選項的類型。
Kind=1:選項表結(jié)束(1字節(jié))
Kind=1:無操作(1字節(jié))
Kind=2:最大報文段長度(4字節(jié))
Kind=3:窗口擴大因子(4字節(jié))
Kind=8:時間戳(10字節(jié))
三、TCP的超時和重傳
對于每個TCP連接,TCP管理4個不同的定時器。
?。?/span>1) 重傳定時器用于當(dāng)希望收到另一端的確認(rèn)。
?。?/span>2) 堅持定時器使窗口大小信息保持不斷流動,即使另一端關(guān)閉了其接收窗口。
(3) ?;疃〞r器可檢測到一個空閑連接的另一端何時崩潰或重啟。
(4) 2MSL定時器測量一個連接處于TIME_WAIT狀態(tài)的時間。
1、往返時間測量
TCP超時和重傳重最重要的就是對一個給定連接的往返時間(RTT)的測量。由于路由器和網(wǎng)絡(luò)流量均會變化,因此TCP應(yīng)該跟蹤這些變化并相應(yīng)地改變超時時間。首先TCP必須測量在發(fā)送一個帶有特別序號地字節(jié)和接收到包含該字節(jié)地確認(rèn)之間的RTT。
2、擁塞避免算法
該算法假定由于分組收到損壞引起的丟失是非常少的,因此分組丟失就意味著在源主機和目的主機之間的某處網(wǎng)絡(luò)上發(fā)生了阻塞。有兩種分組丟失的指示:發(fā)生超時和收到重復(fù)的確認(rèn)。擁塞避免算法需要對每個連接維持兩個變量:一個擁塞窗口cwnd和一個慢啟動門限ssthresh。
(1) 對一個給定的連接,初始化cwnd為1個報文段,ssthresh為65535個字節(jié)。
(2) TCP輸出例程的輸出不能超過cwnd和接收方通告窗口的大小。擁塞避免是發(fā)送方使用的流量控制。前者是發(fā)送方感受到的網(wǎng)絡(luò)擁塞的估計,而后者則與接收方在該連接上的可用緩存大小有關(guān)。
(3) 當(dāng)擁塞發(fā)生時,ssthresh被設(shè)置為當(dāng)前窗口大小的一般(cwnd和接收方通告窗口大小的最小值,但最小為2個報文段)。此外,如果是超時引起了擁塞,則cwnd被設(shè)置為1個報文段。
(4) 當(dāng)新的數(shù)據(jù)被對方確認(rèn)時,就增加cwnd,但增加的方法依賴與是否正在進行慢啟動或擁塞避免。如果cwnd小于或等于ssthresh,則正在進行慢啟動,否則正在進行擁塞避免。
3、快速重傳和快速恢復(fù)算法
如果我們一連串收到3個或以上的重復(fù)ACK,就非常可能是一個報文段丟失了。于是我們就重傳丟失的數(shù)據(jù)報文段,而無需等待超時定時器溢出。
?。?/span>1) 當(dāng)收到第3個重復(fù)的ACK時,將ssthresh設(shè)置為當(dāng)前擁塞窗口cwnd的一半,重傳丟失的報文段,設(shè)置cwnd為ssthresh加上3倍的報文段大小。
(2) 每次收到另一個重復(fù)的ACK時,cwnd增加1個報文段大小并發(fā)送一個1個分組,如果允許的話。
?。?/span>3) 當(dāng)下一個確認(rèn)新數(shù)據(jù)的ACK到達時,設(shè)置cwnd為ssthresh,這個ACK應(yīng)該時在進行重傳后的一個往返時間內(nèi)對步驟1重重傳的確認(rèn)。另外,這個ACK也應(yīng)該是對丟失的分組和收到的第一個重復(fù)的ACK之間的所有中間報文段的確認(rèn)。
4、 ICMP差錯
TCP如何處理一個給定的連接返回的ICMP差錯。TCP能夠遇到的最常見的ICMP差錯就是源站抑制、主機不可達和網(wǎng)絡(luò)不可達。
?。?/span>1) 一個接收到的源站抑制引起擁塞窗口cwnd被置為1個報文段大小來發(fā)起慢啟動,但是慢啟動門限ssthresh沒有變化,所以窗口將打開直到它開放了所有的通路或者發(fā)生了擁塞。
?。?/span>2) 一個接收到的主機不可達或網(wǎng)絡(luò)不可達實際都被忽略,因為這兩個差錯都被認(rèn)為是短暫現(xiàn)象。TCP試圖發(fā)送引起該差錯的數(shù)據(jù),盡管最終有可能會超時。
5、重新分組:
當(dāng)TCP超時并重傳時,它并不一定要重傳同樣的報文段,相反,TCP允許進行重新分組而發(fā)送一個較大的報文段。這是允許的,因為TCP是使用字節(jié)序號而不是報文段序號來進行識別它所要發(fā)送的數(shù)據(jù)和進行確認(rèn)。
四、TCP的堅持定時器
ACK的傳輸并不可靠,也就是說,TCP不對ACK報文段進行確認(rèn),TCP只確認(rèn)那些包含數(shù)據(jù)的ACK報文段。為了防止因為ACK報文段丟失而雙方進行等待的問題,發(fā)送方用一個堅持定時器來周期性地向接收方查詢。這些從發(fā)送方發(fā)出地報文段稱為窗口探查。
五、TCP的?;疃〞r器
如果一個給定的連接在2小時內(nèi)沒有任何動作,那么服務(wù)器就向客戶發(fā)送一個探查報文段??蛻糁鳈C必須處于以下4個狀態(tài)之一。
(1) 客戶主機依然正常運行,并從服務(wù)器可達??蛻舻?/span>TCP響應(yīng)正常,而服務(wù)器也知道對方的正常工作的。服務(wù)器在2小時內(nèi)將?;疃〞r器復(fù)位。
(2) 客戶主機已經(jīng)崩潰,并且關(guān)閉或者正在重新啟動。在任何一種情況下,客戶的TCP都沒有響應(yīng)。服務(wù)器將不能收到對探查的響應(yīng),并在75秒后超時??偣舶l(fā)送10個探查,間隔75秒。
(3) 客戶主機崩潰并已經(jīng)重新啟動。這是服務(wù)器將收到一個對其?;钐讲榈捻憫?yīng),但這個響應(yīng)是一個復(fù)位,使得服務(wù)器終止這個連接。
(4) 客戶主機正常運行,但是從服務(wù)器不可達。
六、TCP的一些性能
1、 路徑MTU發(fā)現(xiàn):
TCP的路徑MTU發(fā)現(xiàn)按如下方式進行:在連接建立時,TCP使用輸出接口或?qū)Χ温暶鞯?/span>MSS中的最下MTU作為其實的報文段大小。路徑MTU發(fā)現(xiàn)不允許TCP超過對端聲明的MSS。如果對端沒有指定一個MSS,則默認(rèn)為536。
一旦選定了起始的報文段大小,在該連接上的所有被TCP發(fā)送的IP數(shù)據(jù)報都將被設(shè)置DF位。如果中間路由器需要對一個設(shè)置了DF標(biāo)志的數(shù)據(jù)報進行分片,它就丟棄這個數(shù)據(jù)報,并產(chǎn)生一個ICMP的“不能分片”差錯。
如果收到這個ICMP差錯,TCP就減少段大小并進行重傳。如果路由器產(chǎn)生的是一個較新的該類ICMP差錯,則報文段大小被設(shè)置位下一跳的MTU減去IP和TCP的首部長度。如果是一個較舊的該類ICMP差錯,則必須嘗試下一個可能的最小MTU。
2、 長肥管道
一個連接的容量=帶寬X時延(RTT)。具有大的帶寬時延乘積的網(wǎng)絡(luò)稱為長肥網(wǎng)絡(luò)(LFN)。一個運行在LFN的TCP連接稱為長肥管道。管道可以被水平拉長(一個長的RTT),或被垂直拉高(較高的帶寬),或兩個方向拉伸。
3、窗口擴大選項:
窗口擴大選項使TCP的窗口定義從16位增加到32位,這并不是通過修改TCP首部來實現(xiàn)的,TCP首部仍然使用16位,而是通過定義一個選項實現(xiàn)對16位的擴大操作來完成的。
4、時間戳選項:
時間戳選項使發(fā)送方在每個報文段中放置一個時間戳值。接收方在確認(rèn)中返回這個數(shù)值,從而允許發(fā)送方為每一個收到的ACK計算RTT。