Linux:TCP協議——三次握手【圖片+文字】
- TCP協議
- 面向連接
- 三次握手
- 雙方狀態的轉變
- 三次握手當中的包序管理
TCP協議
TCP協議:全稱為 “傳輸控制協議(Transmission Control Protocol”). 人如其名, 要對資料的傳輸進行一個詳細的控制,
TCP協議段格式:

源/目的埠號: 表示資料是從哪個行程來, 到哪個行程去;(tcp是傳輸層的協議,端與端之間的資料傳輸,在TCP和UDP協議當中不會體現出IP)
32位序號: 消耗的是發送方維護的序號
32位確認號:告知訊息的發送方期待發送方發送的下一條序號
16位視窗大小:告訴發送方位元組的接收能力
4位TCP報頭長度: 表示該TCP頭部有多少個32位bit(有多少個4位元組); 所以TCP頭部最大長度是15 * 4 = 60
6位標志位:
| 名稱 | 解釋 |
|---|---|
| URG: | 緊急指標是否有效 |
| ACK: | 確認號是否有效 |
| PSH: | 提示接收端應用程式立刻從TCP緩沖區把資料讀走 |
| RST: | 對方要求重新建立連接; 我們把攜帶RST標識的稱為復位報文段 |
| SYN: | 請求建立連接; 我們把攜帶SYN標識的稱為同步報文段 |
| FIN: | 通知對方, 本端要關閉了, 我們稱攜帶FIN標識的為結束報文段 |
16位校驗和: 發送端填充, CRC校驗. 接收端校驗不通過, 則認為資料有問題. 此處的檢驗和不光包含TCP首部, 也包含TCP資料部分,簡單來說就是檢驗TCP資料是否在傳輸程序中失真,
16位緊急指標: 標識哪部分資料是緊急資料;
我們知道tcp協議有三個特征:面向連接、可靠傳輸和面向位元組流接下來我們介紹TCP協議的時候,也是按照這個三個特征來介紹的,
40位元組頭部選項:MMS,最大報文長度,選項的最大位元組數量是40位元組 ;
面向連接
指tcp連接的本質是在建立三次握手時期,通信雙方會協商很多連接當中的資料,例如:MSS,包序號等,
對于TCP而言,如果通信雙方不建立連接則不能進行通信,
三次握手
從連接的建立和終止的角度,我們需要討論三次握手以及四次揮手,這篇文章我們先來討論一下三次握手,不過無論是三次握手還是四次揮手,我們在分析連接的時候,都是從雙方的連接狀態、連接資料包的名稱和包序管理三個方面進行分析的,
三次握手:

TCP資料包 = TCP協議包頭部分 + 應用層遞交給TCP協議的資料
注意:當發起連接或者斷開連接的時候,呼叫connect函式,但是連接發送的syn,syn+ack,ack我們都沒有直接參與,換句話說,在發送這些資料包的時候,我們并沒有給傳輸層的TCP協議提交任何資料,這里的syn,syn+ack,ack全部都是TCP協議報頭的內容,
雙方狀態的轉變
服務端:
| 狀態 | 解釋 |
|---|---|
| CLOSED -> LISTEN] | 服務器端呼叫listen后進入LISTEN狀態, 等待客戶端連接; |
| LISTEN -> SYN_RCVD | 一旦監聽到連接請求(同步報文段), 就將該連接放入內核等待佇列中, 并向客戶端發送SYN確認報文. |
| SYN_RCVD -> ESTABLISHED | 服務端一旦收到客戶端的確認報文, 就進入ESTABLISHED狀態, 可以進行讀寫資料了. |
客戶端:
| 狀態 | 解釋 |
|---|---|
| CLOSED -> SYN_SENT | 客戶端呼叫connect, 發送同步報文段; |
| SYN_SENT -> ESTABLISHED | connect呼叫成功, 則進入ESTABLISHED狀態, 開始讀寫資料 |
其實從個人角度上理解,我認為可以把UDP協議理解成我們平時寄信的行為,而TCP協議則和我們平時打電話類似,而三次握手就類似于通話雙方在進行通話前要確保對方能夠聽到我們說話一樣,

三次握手當中的包序管理
TCP將每個位元組的資料都進行了編號. 即為序列號

每一個ACK都帶有對應的確認序列號, 意思是告訴發送者, 我已經收到了哪些資料; 下一次你從哪里開始發,
TCP連接中維護了兩套序號,一套是客戶端在維護,一套是服務端在維護,兩套序號相互獨立,互不影響,其實這個程序就相當于是有兩個人要交換各自的貨物,然后每個貨物都有自己編號,然后每次給對方發送的時候都會告訴對方自己是從幾號貨物開始發送的,自己希望下一次對方從記號貨物開始給自己發送(表示在自己希望對方下一次發送的序號之前的貨物都已經收到了),而只要自己不發送貨物(資料)(純ACK)貨物對應的序號就不會改變(就不會消耗序號),

總結:(1)三次握手當中,連接雙方在協商各自維護的序號的起始位置SYN(seq=0)表示:
a.客戶端想要和服務端建立連接
b.客戶端告訴了服務端,自己維護的序號的起始位置是0
SYN + ACK(seq=0,ack=1)表示:
a.服務端告訴客戶端想要和客戶端建立連接
b.服務端告訴了客戶端,自己維護的序號是從0號序號開始
c.服務端告訴客戶端,期望客戶端在發送下一條資料的時候,從客戶端的1號序號開始發送
注意:這里的起始序號是通信雙方在三次握手當中協商的,TCP連接的時候,雙方維護的序號不一定是宋0號序號開始的,可以是任意的,但是后續的所有的資料包必須遵守該起始序號,
(2)純ACK資料包不消耗序號
(3)如果帶有應用層資料的TCP資料包,在該資料包中我們消耗的序號當中最大的序號是(seq+資料長度-1)
例如:PSH(seq=1):aaa[1,2,3],消耗的序號為:1+3-1 = 3
(4)回復確認信號的時候,需要告知訊息發送方接下來發送資料的起始序號即:ACK = 發送方發送的資料當中的seq + len
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/272532.html
標籤:其他
上一篇:快速排序 C/C++
下一篇:C語言的一些“小細節“(1)
