TCP協議結構簡介
TCP在IP中的封裝
以下為TCP在IP數據報中的封裝

TCP頭部

源端口和目的端口
一個IP地址和端口的組合稱為“套接字”或“端點”。
所以IP協議中的源IP地址和目的地址

和TCP協議中的源端口和目的端口,
組成了“一對”套接字(發送端的套接字和接收端的套接字)。
序列號
每一個“TCP報文段中的第一個字節”都會被賦予一個序列號。
序列號是個32位數,到達2^32-1后會再回到0.
確認號(TCP返回報文使用)
也稱ACK號或ACK字段。
確認號包含的值為:“確認號的發送方”希望接收的下一個序列號。(即最后接收成功的序列號+1)
頭部長度
該字段表示TCP頭部的長度,以32位字為單位。
由於“選項字段”大小是可變的,所以“頭部長度”字段是必須的。
TCP頭部長度最大為60字節,如果沒有選項字段,則為20個字節。
8種狀態標識
以下各個標識表示了“該TCP報文段”是干什么的。
如:
SYN和ACK可能同時為1,它表示的就是建立連接之后的響應。
單個的一個SYN,它表示的只是建立連接。
1、CWR:擁塞窗口減(發送方降低它的發送速率)。
2、ECE:ECN回顯(發送方接收到了一個更早的擁塞通告)
3、URG:緊急(緊急指針字段有效,很少用)
4、ACK:確認(確認號字段有效,連接建立后一般都是啟用狀態)
5、PSH:推送(幾乎沒被用到)
6、RST:重置連接(連接取消)
7、SYN:表示建立連接
8、FIN:該報文的發送方已經結束向對方發送數據
窗口大小
在TCP協議里,一個分組從發送端發送到接收端后,接收端應該返回一個ACK號。
如之前所說,每一個分組都是從“序列號”開始的,我們定一個術語“窗口”,來表示:已發送的分組們,但這些分組還未返回確認號(ACK號)。
窗口中的分組數量稱之為:“窗口大小”。
下圖為發送方的窗口以及其他分組隊列:

如圖所示,如果發送方下一步接收到了序列號為4的分組的“ACK”,則“窗口向右滑動一個分組”,意味着分組4可以釋放了,分組7可以發送了。這種行為稱之為:“窗口滑動協議”。
TCP校驗和
該校驗算法與IP、ICMP、UDP校驗算法一致,其覆蓋了TCP頭部和數據中的一些字段。
緊急指針
只有在有URG字段時才有效。該指針是一個加到“序列號字段”上的正偏移,以產生“緊急數據”的最后一個字節的序列號。
選項
最常見的選項字段為:“最大段大小”字段,稱為MSS。
連接的每個端點(套接字)一般在它發送的第一個報文段上指定該選項。
下面我們會詳講這些額外“選項”。
TCP連接
TCP連接的建立與終止
一個TCP連接由一個4元組構成,它們分別是發送端ip地址,發送端tcp端口,接收端ip地址,接收端tcp端口。也就是說,tcp連接由一對套接字構成。
TCP連接通常分為3個階段:啟動、數據傳輸(連接已建立)、退出(連接關閉)。
過程如下圖:

建立連接
第一次握手:(問服務端“你能不能聽見我說話?”)
客戶端主動發送一個TCP報文段,
里面SYN字段設為1(表示建立連接,即“詢問”),且包含了該報文段的初始“序列號”(記為ISN(c),該初始序列號是隨機產生的)。
通常,客戶端還會借此發送多個“選項”。
第二次握手:(回答客戶端說“能聽見你說話”,但問客戶端“你能不能聽見我說話?”)
服務端也發送自己的TCP報文段作為響應,
里面的SYN和ACK字段設為1(表示建立連接之后的響應,即詢問+響應)。
該報文段的序列號為它自己的初始“序列號”(記為ISN(c),該初始序列號是隨機產生的)。
該報文段還包含“確認號”,為“第一次握手時獲得的ISN(c)+1”。(之前講過,確認號表示:“確認號的發送方希望接收的下一個序列號”。即接收成功的序列號+1)
第三次握手:(回答服務端說“能聽見你說話”)
客戶端響應服務端,
里面的ACK字段為1(即響應)。
該報文段的序列號為ISN(c)+1(剛好與第二次握手的確認號相呼應)。
確認號為ISN(s)+1(即第二次握手中的序列號+1)
關閉連接
連接的雙方都能關閉連接,但傳統情況下是客戶端負責發起關閉連接。
1、連接的主動關閉者(圖中為客戶端)發送一個FIN=1(表示已經結束向對方發送數據)和ACK=1(表示接收到了之前發送過來的最后一個數據)的報文段。
2、被動關閉者,先發個ACK報文段,表示:已經接收到剛剛的報文了。再發個ACK+FIN報文字段,此時被動關閉者的身份又轉換成了主動關閉者,表示它也要關閉了。
3、最后,客戶端發送一個ACK報文表示知道了。
TCP半關閉
所謂半關閉就是:
關閉的發起端發送了“要求關閉的報文”,(客戶端發送:FIN+ACK)
接收端返回響應表示接收到了(服務端發送:ACK)
但被動關閉方可能數據沒傳完,所以繼續傳了很多數據給發起端,
然后發起端確認接收到這些數據了,
然后被動關閉方再發送“關閉報文”(服務端發送:FIN(此時沒有ACK了,因為ACK的作用是表示“接收到了你發來的報文”,而客戶端已經沒有發來報文了))
客戶端發個響應表示知道了(客戶端發送:ACK),TCP連接關閉。
(即:連接的一方關閉,另一方仍然傳輸數據直到它關閉為止)
同時打開與關閉
所謂同時打開關閉就是:
通信雙方在接收到來自對方的SYN報文段(SYN=1表示建立連接)之前,雙方都要先給對方發送一個SYN報文。
然后雙方再響應各自收到的報文(即雙方都再發送SYN+ACK報文段)。
TCP選項
之前說過了,TCP頭部包含了多個可選的“選項”字段。
下面詳細介紹幾個比較常用的選項:
最大段大小選項(MSS)
最大段大小是指TCP協議所能允許的從對方接收到的最大報文段(即通信對方所能使用的最大報文段)。
當建立一條TCP連接時,通信的每一方都應在SYN報文段的MSS選項中說明自己所允許的“最大報文段”。
最大段的默認大小為:536字節。
選擇確認選項(SACK)
在沒有加這個選項之前,假設發送端按序發送給接收端5個分組報文,
客戶端發送第1個,接收端返回ACK表示確認。
客戶端發送第2個,中途出了問題沒法送到。接收端返回響應表示剛剛的數據2報文錯誤。
客戶端發送第3個,(客戶端不能響應,因為沒正確的接收到數據2)
客戶端發送第4個,(客戶端不能響應,因為沒正確的接收到數據2)
此時客戶端收到報文2的錯誤響應。
客戶端再發送第2個,接收端返回ACK表示確認。
客戶端再發送第3個,接收端返回ACK表示確認。
客戶端再發送第4個,接收端返回ACK表示確認。
······
由此可看出,客戶端重復的發送了2以后的報文。
如果“TCP接收方”能提供“選擇確認選項(SACK)”,
那么服務端即使沒接收到數據2,也依然會正常接收數據2以后的報文。
用戶超時選項(UTO)
用戶超時數值指明了TCP發送者願意等待ACK確認的時間。
認證選項(TCP-AO)
該選項使用一種散列加密算法以及連接雙方共同維護一個秘密值來認證每一個報文段。
TCP認證選項不僅提供各種加密算法,還使用帶內信令來確認秘鑰是否改變。
TCP狀態轉換
之前提到了TCP在不同的階段會發送各種各樣的報文段,而這些決定TCP應該做什么的規則,其實是由TCP所屬的“狀態”決定的。
而TCP的狀態會在各種觸發條件下改變。
我們還是來看一下TCP的連接與關閉:

ESTABLISHED是通信雙方雙向傳輸數據的狀態。
FIN_WAIT_1,FIN_WAIT_2,TIME_WAIT稱作:“主動關閉”狀態。
它們表示當本地應用程序發起一個請求時會進入的狀態集合。
CLOSE_WAIT,LAST_WAIT表示“被動關閉”,
這些狀態與等待一個節點確認一個FIN報文段相關。
