1. 簡介
TCP提供一種可靠的面向連接的全雙工服務(wù),位于傳輸層。
2. TCP報文段結(jié)構(gòu)
TCP報文段包括首部字段和數(shù)據(jù)字段,其中數(shù)據(jù)字段來自于應(yīng)用層的數(shù)據(jù),最大長度為MSS。
首部字段
- 源端口號(16 bit):發(fā)送進程所占用的端口號
- 目的端口號(16 bit):接收進程所占用的端口號
- 序號(32 bit):傳輸方向上對數(shù)據(jù)字節(jié)流中的每一個字節(jié)編號,這個序號就是發(fā)送方要傳輸?shù)膱笪亩沃袛?shù)據(jù)流的第一個字節(jié)的序號。
- 確認(rèn)號(32 bit):接受方對接受到的報文段作出確認(rèn),確認(rèn)號即是希望接受的下一個報文段數(shù)據(jù)字段中的第一個字節(jié)的編號。
- 首部長(4 bit):標(biāo)識首部的大小以多少個4字節(jié)為單位,最大為15,即60字節(jié)。
- 標(biāo)志位(6 bit):
- URG:表示緊急指針是否有效。
- ACK:表示確認(rèn)號是否有效。
- PSH:表示接收方應(yīng)立即從緩沖讀走數(shù)據(jù),將數(shù)據(jù)傳給上層。
- RST:表示要求對方重新建立連接。
- SYN:表示請求建立一個連接。
- FIN:表示關(guān)閉連接。
- 接受窗口(16 bit):用于告知接收方自己還有多少緩存空間可用,因為TCP是全雙工通信,雙方都維持一個接受窗口。
- 檢驗和(16 bit):接收端用檢驗和檢驗報文段有無損壞。
- 緊急數(shù)據(jù)指針(16 bit):當(dāng)URG位為1時,此緊急數(shù)據(jù)指針指向緊急數(shù)據(jù)的最后一個字節(jié)。
- 選項字段:該字段是可選和變長的字段,可用于發(fā)送方與接收方協(xié)商最大報文段長度(MSS)。
3. 可靠性實現(xiàn)
連接建立(三次握手)
- 第一次:客戶端發(fā)送SYN報文請求建立連接,然后進入SYN_SEND狀態(tài)。
- 第二次:服務(wù)器收到SYN報文,確定建立連接并發(fā)送SYN + ACK報文,然后進入SYN_RECV狀態(tài)。
- 第三次:客戶端收到SYN + ACK報文,并對服務(wù)器的請求進行確認(rèn),發(fā)送ACK報文,然后進入ESTABLISH狀態(tài)。
為什么要三次握手?
現(xiàn)在考慮兩次握手的情況:<<計算機網(wǎng)絡(luò)>>謝仁希版里面說防止已失效的連接請求報文段,意思是TCP第一次握手客戶端發(fā)給服務(wù)器的SYN報文段出現(xiàn)延遲,然后客戶端發(fā)現(xiàn)超時重傳SYN報文段,這一次服務(wù)器收到并回應(yīng)一個ACK報文,服務(wù)器端的連接建立,收到ACK報文的客戶端也成功建立了連接。然而此時第一次發(fā)出的已失效的SYN報文此時到達了服務(wù)器,服務(wù)器以為發(fā)現(xiàn)是客戶端的連接建立請求,同一建立起連接,然后發(fā)回一個ACK報文,客戶端收到后不理睬,那服務(wù)器白白浪費TCP通信資源。但采用三次握手可以解決這個問題。
連接拆除(四次揮手)
- 第一次:客戶端發(fā)送FIN+ACK報文,進入FIN_WAIT_1狀態(tài),表示沒有數(shù)據(jù)要發(fā)送了。
- 第二次:
- 服務(wù)器收到了FIN+ACK報文,知道了斷開請求,發(fā)送一個ACK報文,然后服務(wù)器進入CLOSE_WAIT狀態(tài),表示可能還有數(shù)據(jù)要發(fā)送。
- 客戶端收到了服務(wù)器的ACK報文進入了FIN_WAIT_2狀態(tài)。
- 第三次:服務(wù)器向客戶端發(fā)送FIN+ACK報文,然后進入LAST_ACK狀態(tài)等待客戶端的回應(yīng)。
- 第四次:客戶端收到FIN+ACK報文,知道了斷開連接的請求,接著客戶端發(fā)送ACK報文然后進入TIME_WAIT狀態(tài),等待2MSL時間服務(wù)器沒有在響應(yīng)就最終進入CLOSE狀態(tài)。
為什么要等待2MSL時間?
- MSL是一個IP數(shù)據(jù)報在網(wǎng)絡(luò)中的最大生存時間,如果客戶端不等待2MSL而是直接進入CLOSED狀態(tài),服務(wù)端可能沒有接收到最后一次ACK包會在超時重傳FIN包,此時因為客戶端已經(jīng)進入CLOSED狀態(tài),所以服務(wù)端就不會收到ACK報文而是收到RST報文。所以等待2MSL時間是防止最后一次握手ACK報文沒有到達對方而觸發(fā)重傳FIN準(zhǔn)備的。
- 讓前一次使用這個端口的連接傳輸?shù)臄?shù)據(jù)到達接收方或消失,避免與新建立的連接數(shù)據(jù)混淆。
流量控制
TCP是全雙工的通信協(xié)議,在通信兩端都維持有一個發(fā)送窗口和接受窗口,對于一個發(fā)送方和一個接收方來說,接收方的接收窗口大小受到接收緩存大小的限制,如果發(fā)送方發(fā)送窗口大小持續(xù)增大導(dǎo)致發(fā)送速率增加,而接受緩存過快填滿而導(dǎo)致接收窗口大小減小,結(jié)果數(shù)據(jù)可能溢出。所以動態(tài)調(diào)整接收窗口就變得非常重要,可以通過TCP報文的窗口字段告知發(fā)送方本方還有多少緩存空間可用,這也就是流量控制。
擁塞控制
擁塞控制是對于整體網(wǎng)絡(luò)(包括路由器、交換機)出現(xiàn)擁塞的進行控制, 不同于流量控制的點對點控制,TCP的擁塞控制由4個核心算法組成。
慢啟動(Slow Start)
在發(fā)送方維持一個額外的擁塞窗口變量cwnd(congestion window),這個擁塞窗口的大小取決于網(wǎng)絡(luò)的擁塞程度,而流量控制的窗口取決于接收方的接受緩存,最終發(fā)送方的發(fā)送窗口大小應(yīng)該為兩者中的最小值。
- 一開始,擁塞窗口的大小設(shè)置為一個MSS大小,即允許發(fā)送一個報文段
- 發(fā)送完窗口所允許發(fā)送的報文段后,接收到一個對該報文段ACK報文段后,cwnd翻倍(cwnd = cwnd * 2)
- 接著再發(fā)送完所有允許發(fā)送的2個報文段后,接收到兩個ACK報文段后cwnd再次翻倍
- 直到網(wǎng)絡(luò)出現(xiàn)擁塞
擁塞避免(Congestion Avoidance)
上面說到慢啟動的過程持續(xù)到網(wǎng)絡(luò)出現(xiàn)擁塞,即出現(xiàn)超時還未收到ACK報文,此時就要進行擁塞避免:
- 將慢啟動閥值
ssthresh設(shè)置為當(dāng)前擁塞窗口cwnd的一半 - 將cwnd的大小設(shè)置為1個MSS,重新執(zhí)行慢啟動算法
- 當(dāng)cwnd的大小達到
ssthresh后的增量變成1,即只增加1個MSS大小
快速重傳(Fast Retransmit)
快速重傳的目的是想讓發(fā)送方在超時之前快速重傳丟失的報文段。當(dāng)發(fā)送方連續(xù)收到3個冗余的ACK就會執(zhí)行快速重傳。
快速恢復(fù)(Fast Recovery)
連續(xù)收到3個冗余的ACK其實也表示網(wǎng)絡(luò)出現(xiàn)擁塞導(dǎo)致丟包,這時執(zhí)行與擁塞避免的類似操作:
- 將慢啟動閥值
ssthresh設(shè)置為當(dāng)前擁塞窗口cwnd的一半 - 將cwnd的大小也設(shè)置為當(dāng)前擁塞窗口cwnd的一半,執(zhí)行擁塞避免算法
第一步與擁塞避免的第一步相同,但cwnd不從1個MSS大小開始執(zhí)行慢啟動指數(shù)增長,而是減半執(zhí)行擁塞避免線性增長,進行快速恢復(fù)。
4. 最后
現(xiàn)在總結(jié)下TCP的可靠性具體表現(xiàn)在:
- 連接建立與拆除的可靠性實現(xiàn)
- 確認(rèn)與重傳機制
- 數(shù)據(jù)校驗
- 流量控制
- 擁塞控制