抓包分析 TCP 握手和揮手

前言

首先需要明確的是 TCP 是一個可靠傳輸協議,它的所有特點最終都是為了這個可靠傳輸服務。在網上看到過很多文章講 TCP 連接的三次握手和斷開連接的四次揮手,但是都太過于理論,看完感覺總是似懂非懂。反復思考過后,覺得我自己還是偏工程型的人,要學習這些理論性的知識,最好的方式還是要通過實際案例來理解,這樣才會具象深刻。本文通過 Wireshark 抓包來分析 TCP 三次握手四次揮手,如果你也對這些理論感覺似懂非懂,那么強烈建議你也結合抓包實踐來強化理解這些理論性的知識。

三次握手

TCP 建立連接的三次握手是連接的雙方協商確認一些信息(Sequence number、Maximum Segment Size、Window Size 等),Sequence number 有兩個作用:一個是 SYN 標識位為 1 時作為初始序列號(ISN),則實際第一個數據字節的序列號和相應 ACK 中的確認號就是這個序列號加 1;另一個是 SYN 標識位為 0 時,則是當前會話的 segment(傳輸層叫 segment,網絡層叫 packet,數據鏈路層叫 frame)的第一個數據字節的累積序列號。Maximum Segment Size 簡稱 MSS,表示最大一個 segment 中能傳輸的信息(不含 TCP、IP 頭部)。Window Size 表示發送方接收窗口的大小。下面看看我在本地訪問博客 mghio 的三次握手過程:

three-way-hand-shake.jpg

圖中三個小紅框表示與服務器建立連接的三次握手。

  1. 第一步,client 端(這個示例也就是瀏覽器)發送 SYN 到 server 端;
  2. 第二步,server 端收到 SYN 消息后,回復 SYN + ACK 到client 端,ACK 表示已經收到了 client 的 SYN 消息;
  3. 第三步,client 端收到回復 SYN + ACK 后,也回復一個 ACK 表示收到了 server 端的 SYN + ACK 了,其實

到這一步,client 端的 60469 端口已經是 ESTABLISHED 狀態了。
可以看到,其實三次握手的核心目的就是雙方互相告知對象自己的 Sequence number,藍框是 client 端的初始 Sequence number 和 client 端回復的 ACK,綠框是 server 端的初始 Sequence number 和 client 端回復的 ACK。這樣協商好初始 Sequence number 后,發送數據包時發送端就可以判斷丟包和進行丟包重傳了。

三次握手還有一個目的是協商一些信息(上圖中黃色方框是 Maximum Segment Size,粉色方框是 Window Size)。

three-way-hand-shake-dg.jpg

到這里,就可以知道平常所說的建立TCP連接本質是為了實現 TCP 可靠傳輸做的前置準備工作,實際上物理層并沒有這個連接在那里。TCP 建立連接之后時擁有和維護一些狀態信息,這個狀態信息就包含了 Sequence number、MSS、Window Size 等,TCP 握手就是協商出來這些初始值。而這些狀態才是我們平時所說的 TCP 連接的本質。因為這個太重要了,我還要再次強調一下,TCP 是一個可靠傳輸協議,它的所有特點最終都是為了這個可靠傳輸服務

四次揮手

下面再來看看,當關閉瀏覽器頁面是發生斷開連接的四次揮手過程:

tcp-close-sequence.jpg

相信你已經發現了,上圖抓包抓到的不是四次揮手,而是三次揮手,這是為何呢?

這是由于 TCP 的時延機制(因為系統內核并不知道應用能不能立即關閉),當被揮手端(這里是 server 的 443 端口)第一次收到揮手端(這里是 client 的 63612 端口)的 FIN 請求時,并不會立即發送 ACK,而是會經過一段延遲時間后再發送,但是此時被揮手端也沒有數據發送,就會向揮手端發送 FIN 請求,這里就可能造成被揮手端發送的 FIN 與 ACK 一起被揮手端收到,導致出現第二、三次揮手合并為一次的現象,也就最終呈現出“三次揮手”的情況。

斷開連接四次揮手分為如下四步(假設沒有出現揮手合并的情況):

  1. 第一步,client 端主動發送 FIN 包給 server 端;
  2. 第二步,server 端回復 ACK(對應第一步 FIN 包的 ACK)給 client,表示 server 知道 client 端要斷開了;
  3. 第三步,server 端發送 FIN 包給 client 端,表示 server 端也沒有數據要發送了,可以斷開了;
  4. 第四步,client 端回復 ACK 包給 server 端,表示既然雙發都已發送 FIN 包表示可以斷開,那么就真的斷開了啊。

下面是 TCP 連接流轉狀態圖(其中 CLOSED 狀態是虛擬的,實際上并不存在),這個圖很重要,記住這個圖后基本上所有的 TCP 網絡問題就可以解決。

Xnip2022-11-06_14-30-17.jpg

其中比較難以理解的是 TIME_WAIT 狀態,主動關閉的那一端會經歷這個狀態。這一端停留在這個狀態的最長時間是 Maximum segment lifetime(MSL)的 2 倍,大部分時候被簡稱之為 2MSL。存在 TIME_WAIT 狀態有如下兩個原因:

  1. 要可靠的實現 TCP 全雙工連接終止;
  2. 讓老的重復 segment 在網絡中消失(一個 sement 在網絡中存活的最長時間為 1 個 MSL,一來一回就是 2 MSL);

為什么握手是三次,而揮手是四次?

嘿嘿,這是個經典的面試題,其實大部分人都背過揮手是四次的原因:因為 TCP 是全雙工(雙向)的,所以回收需要四次......。但是再反問下:握手也是雙向的,但是為什么是只要三次呢?

網上流傳的資料都說 TCP 是雙向的,所以回收需要四次,但是握手也是雙向(握手雙方都在告知對方自己的初始 Sequence number),那么為什么就不用四次握手呢?所以凡事需要多問幾個為什么,要有探索和懷疑精神。

你再仔細回看上面三次握手的第二步(SYN + ACK),其實是可以拆分為兩步的:第一步回復 ACK,第二步再發 SYN 也是完全可以的,只是效率會比較低,這樣的話三次握手不也變成四次握手了。

看起來四次揮手主要是收到第一個 FIN 包后單獨回復了一個 ACK 包這里多了一次,如果能像握手那樣也回復 FIN + ACK 那么四次揮手也就變成三次了。這里再貼一下上面這個揮手的抓包圖:

three-way-hand-shake.jpg

這個圖中第二個紅框就是 server 端回復的 FIN + ACK 包,這樣四次揮手變成三次了(如果一個包算一次的話)。這里使用四次揮手原因主要是:被動關閉端在收到 FIN 后,知道主動關閉端要關閉了,然后系統內核層會通知應用層要關閉,此時應用層可能還需要做些關閉前的準備工作,可能還有數據沒發送完,所以系統內核先回復一個 ACK 包,然后等應用層準備好了主動調 close 關閉時再發 FIN 包。

而握手過程中就沒有這個準備過程了,所以可以立即發送 SYN + ACK(在這里的兩步合成一步了,提高效率)。揮手過程中系統內核在收到對方的 FIN 后,只能 ACK,不能主動替應用來 FIN,因為系統內核并不知道應用能不能立即關閉。

總結

TCP 是一個很復雜的協議,為了實現可靠傳輸以及處理各種網絡傳輸中的 N 多問題,有一些很經典的解決方案,比如其中的網絡擁塞控制算法、滑動窗口、數據重傳等。強烈建議你去讀一下 rfc793TCP/IP 詳解 卷1:協議 這本書。

如果你是那些純看理論就能掌握好一門技能,然后還能舉三反一的人,那我很佩服你;如果不是,那么學習理論知識注意要結合實踐來強化理解理論,要經過反反復復才能比較好地掌握一個知識,講究技巧,必要時要學會通過工具來達到目的。

最后 TCP 所有特性基本上核心都是為了實現可靠傳輸這個目標來服務的,然后有一些是出于優化性能的目的。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容