以下內容來自于小碼哥"網絡協(xié)議從入門到底層原理"


分析一下自己抓包的結果

上圖是一個典型的三次握手
我們來分析一下第一次握手
-
第一次握手
image.png
第一次握手的數(shù)據(jù)部分的長度是0個字節(jié), TCP首部占44個字節(jié), 其中固定部分長度是20個字節(jié), 選項部分長度是24個字節(jié)
TCP首部存儲的是Sequence的raw值,而不是相對值 見下圖

我們把這個值稱為s1, 這個s1記錄的是客戶端->服務器發(fā)送的每一個segment的第一個字節(jié)的編號
-
我們來分析一下第二次握手
image.png -
我們來分析一下第三次握手
image.png
三次握手后, TCP連接就成功建立
建立了發(fā)數(shù)據(jù)的通道, 這是一個全雙工的通道, 即客戶端也可以發(fā)給服務器, 服務器也可以發(fā)給客戶端
-
然后客戶端發(fā)給服務器
HTTP請求
image.png -
服務端收到客戶端發(fā)過來的
HTTP請求之后, 就會發(fā)給客戶端一個收到的ACK響應
image.png -
然后服務端就開始發(fā)數(shù)據(jù)給客戶端了
image.png
看上圖可以知道: 上圖的ACK全部是719, 這是為什么呢? 719是ACK的相對值, 即718 + 1 = 719, 718是客戶端發(fā)給服務器的HTTP請求的長度, 即TCP的數(shù)據(jù)部分, 所以ACK的raw值應該是期望客戶端發(fā)給服務器的下一個包的第一個字節(jié)的值, 即s1 + b1 + 1, 因為在這個過程中, 并沒有收到客戶端發(fā)給服務器的任何數(shù)據(jù)包, 那么這個值就始終是s1 + b1 + 1, 相對值就始終是719.
但是會變化的是序號seq值, seq值是上一個包的seq值, 加上長度Len生成的, 比如上圖中最后一個包的seq是4771, 而4771 = 4755 + 16, 4755就是上一個服務器發(fā)給客戶端包的seq值. 如果把上圖這7個包的長度分別記為k1, k2, k3, k4, k5, k6, k7的話, 那么最后一個包的seq相對值就是1 + k1 + k2 + k3 + k4 + k5 + k6, raw值就是s2 + 1 + k1 + k2 + k3 + k4 + k5 + k6,
讓我們看看是不是這樣, 我們點開最后一個包:


s2的值果然就是這樣
- 接下來就是客戶端對服務端的
ACK回應, 告訴客戶端, 我收到包了:

注意看最后一個包的ACK是6223, 這就是服務器發(fā)給客戶端的最后一個包的seq + Len:

- 就這樣反反復復, 直到服務端這邊已經發(fā)完了全部數(shù)據(jù), 那么就會給客戶端返回一個
200:
image.png
從上面的圖可以看到, 客戶端這邊發(fā)的好多包的seq都為719, 這是因為客戶端發(fā)的包都只是一個ACK回應, 表示: 哦, 我收到了, 這樣的包的長度Len都為0, 所以seq都為s1 + b1 + 1, 就是相對值為719(718 + 1), raw值為2751725119(718 + 1 + s1(2751724400))
到此, 傳輸層的三次握手就分析完了.
TCP-建立連接-狀態(tài)解讀
-
CLOSED:client處于關閉狀態(tài) -
LISTEN:server處于監(jiān)聽狀態(tài), 等待client連接 -
SYN-RCVD: 表示server接受到了SYN報文, 當收到client的ACK報文后, 它會進入到ESTABLISHED狀態(tài) -
SYN-SENT:表示client已發(fā)送SYN報文, 等待server的第2次握手
image.png
TCP-建立連接-前2次握手的特點
SYN都設置為1數(shù)據(jù)部分的長度都為
0TCP頭部的長度一般是32字節(jié)
-- 固定頭部:20字節(jié)
-- 選項部分:12字節(jié)雙方會交換確認一些信息
-- 比如MSS, 是否支持SACK,Window scale(窗口縮放系數(shù))等
TCP-建立連接-疑問
為什么建立連接的時候, 要進行
3次握手,2次不行嗎?
-- 主要目的: 防止server端一直等待, 浪費資源如果建立連接只需要
2次握手, 可能會出現(xiàn)的情況
-- 假設client發(fā)出的第一個連接請求報文段, 因為網絡延遲, 在連接釋放以后的某個時間才到達server
-- 本來這是一個早已失效的請求, 但server收到此失效的請求后, 誤認為是client再次發(fā)出的一個新的連接請求
-- 于是server就向client發(fā)出確認報文段, 同意建立連接
-- 如果不采用"3次握手", 那么只要server發(fā)出確認, 新的連接就建立了
-- 由于現(xiàn)在client并沒有真正想連接服務器的意愿, 因此不會理睬server的確認, 也不會向server發(fā)送數(shù)據(jù)
-- 但在server卻以為新的連接已經建立, 并一直等待client發(fā)來數(shù)據(jù), 這樣,server的很多資源就白白浪費了采用"三次握手"的辦法可以防止上述現(xiàn)象發(fā)生
-- 例如上述情況,client沒有向server的確認發(fā)出確認,server由于收不到確認, 就知道client并沒有要求建立連接第
3次握手失敗了, 會怎么處理?
-- 此時server的狀態(tài)為SYN-RCVD, 若等不到client的ACK,server會重新發(fā)送SYN+ACK包
-- 如果server多次重發(fā)SYN+ACK都等不到client的ACK, 就會發(fā)送RST包, 強制關閉連接







