關于TCP三次握手的理論知識,往上一搜一大片,本文就跳過理論,直接上手。Let’s go。
準備知識
抓一個TCP三次握手的包
開啟三個窗口,窗口1執行命令:
這個命令用來抓包,抓的是7899端口的包。-A和-X是為了顯示詳細的包內容,方便分析。如果不習慣用tcpdump直接分析,也可以使用wireshark,更加直觀一些。
窗口2執行命令:
該命令監聽7899端口,相當于啟動了一個監聽7899端口的server。當然你要是有興趣的話,可以用代碼寫一個server。
窗口3執行命令:
這個命令是向127.0.0.1:7899建立連接,相當于client執行connect函數。
這個命令一執行,就會連接到7899端口上 ,在第一個窗口上立即就會抓到連續的三個包,如下圖所示:
如上步驟,演示了TCP建立連接的過程,tcpdump抓到的三個包,正好就是三次握手。
很多資料講解三次握手時,都會有一幅類似于這樣的圖:
我們對應抓到的三個包來看。
第一個包:
- 127.0.0.1.48448 > 127.0.0.1.7899 說明是從client 發往server的, client的端口是48448
第二個包:
- 127.0.0.1.7899 > 127.0.0.1.48448 說明是從server發往client的
第三個包:
- 127.0.0.1.48448 > 127.0.0.1.7899 從client發往server
這個步驟,和上圖大致是能一一對應上的。
除了這些簡而易見的信息,還有一些 可能一時半會兒看不懂的東西,比如:
要了解這些東西,需要先了解TCP協議棧。
需要C/C++ Linux服務器架構師學習資料加qun812855908獲?。?a href="http://m.xsypw.cn/soft/special/" target="_blank">資料包括C/C++,Linux,golang技術,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK,ffmpeg等),免費分享
了解一下TCP協議棧
首先,我們應該知道,一個完整的以太網幀,包含了ethdr + iphdr + tcpdhr + data + etend
其中,以太網頭占14字節,IP頭占20字節,TCP頭占20字節,以太網尾占4字節,應用數據大小不定,但不會超過一個MTU。
因為我們只研究三次握手,所以關于以太網幀,了解這些就夠了。
我們再來看看具體的TCP協議棧:
TCP協議棧包含:
16位源端口號,占2字節
16位目的端口號,占2字節
32位序號(seq),占4字節
32位確認序號(ack),占4字節
4位首部長度,占0.5字節
6位保留位,占0.75字節
6位標志位,占0.75字節, 以上:4位首部長度+6位保留長度+6位標志位,合計16位,計2字節
標志位包括:
URG
- 緊急指針標志
- 此標志用于將輸入數據標識為“緊急”。這樣的進入段不必等待直到先前段被接收端消耗,而是直接發送并立即處理。
ACK - 用于確認數據包的成功接收
PSH - 推送標志
- 就是指數據包到達接收端以后,不對其進行隊列處理,而是盡可能的將數據交給應用程序處理
RST - 重置標志
- 當段到達不用于當前連接時,使用復位標志,表示主機已重置連接
SYN - 發送/同步標志
- 用來建立連接,一般和ACK搭配使用
FIN - 結束標志
- 用于結束一個TCP會話, 一般用于四次揮手
16位窗口大?。╳indow size),占2字節
16位校驗和(checksum),占2字節
16位緊急指針,占2字節
庖丁解牛,深度剖析TCP協議棧的三次握手
有了以上這些知識,我們再來解析上面的協議棧。
第一個包
0x0000: 4510 003c dbf7 4000 4006 60b2 7f00 0001 E..<..@.@.`.....
0x0010: 7f00 0001 bd40 1edb b5dc f355 0000 0000 .....@.....U....
0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
0x0030: 7a57 2314 0000 0000 0103 0307 zW#.........
十六進制報文中,前20個字節是IP協議頭,后20個字節雖然也屬于TCP協議 ,但是是可選項option,并非標準的TCP協議一定有的內容,所以我們真正關心的內容 , 是下面高亮的部分:
即:
接下來,我們逐個字節解析:
16位源端口, 即 bd40, 轉換成10進制為48448
16位目的端口,即1edb,轉換成10進制為7899
- 從以上信息可知,該條消息是從48448發往7899端口,即客戶端發往服務端
32位序號:b5dc f355, 即3051156309
32位確認號:0000 0000,即0
后面三個域由于不是 完整的字節,放在一塊解析:
- a002翻譯成二進制 ,為:1010 0000 0000 0010
- 其中,4位首部長度,為1010,即10
- 6位保留字段,即0000 00,不做解釋
- 6位標志位,即00 0010
標志位要解釋一下 :
標志位哪一位設置為1,就代表當前屬于什么包
由上面對應關系,可知當前是一個SYN包。
16位窗口大小:ffd7, 即65495
16位校驗和,即:fe30
16位緊急指針,即0000
由以上內容,我們提取一些關鍵信息:
第一次握手:
- 客戶端發往服務端
- 標志位為SYN
- seq為3051156309
- ack為0
第二個包
0x0000: 4500 003c 0000 4000 4006 3cba 7f00 0001 E..<..@.@.<.....
0x0010: 7f00 0001 1edb bd40 7916 41ca b5dc f356 .......@y.A....V
0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
0x0030: 7a57 2314 7a57 2314 0103 0307 zW#.zW#.....
由上面的知識,我們知道TCP報文主要是下面這段:
通過同樣的方法,可以解析出:
第二次握手:
- 服務端發往客戶端
- 標志位為ACK+SYN
- seq為2031501770
- ack為3051156310, 正好是第一次握手的seq+1
第三個包
0x0000: 4510 0034 dbf8 4000 4006 60b9 7f00 0001 E..4..@.@.`.....
0x0010: 7f00 0001 bd40 1edb b5dc f356 7916 41cb .....@.....Vy.A.
0x0020: 8010 0200 fe28 0000 0101 080a 7a57 2314 .....(......zW#.
0x0030: 7a57 2314 zW#.
TCP協議部分:
可以解析出 :
第三次握手:
- 客戶端發往服務端
- 標志位:ACK
- seq為3051156310,為第一次我收的 seq+1,也是第二次握手的ack
- ack為2031501771, 為 第二次握手的seq+1
歸納:
以上內容,如果用比較直觀的方式總結一下 ,大約如下圖:
為什么需要三次握手
又回到老生常談的話題:為什么需要三次握手?少一次行不行?只握手一次成不成?
在聊這個話題之前,我們引入一下著名科幻小說《三體》中葉文杰教主和三體文明建立聯系的過程。
首先,葉教主向三體文明發送了一條消息,緊接著,三體人回復了一條消息,內容是“不要回答,不要回答,不要回答!”然后葉教主回復了這條消息 ,導致地球成功被三體人定位。
不得不說,大劉是懂TCP協議的。至少他懂三次握手的重要性。
第一次發消息,你說三體人收到沒有?肯定是收到了的。但這個連接可靠不?明顯不可靠。對于三體人來說,他怎么知道這個消息是誰發的?發消息的文明是否還活著?對于地球來說,更是如此,他怎么知道 這條消息對方肯定收到了?又沒有人收?
第二次發消息,三體人差不多要把ACK標志寫在臉上了,就是明明白白告訴你,我這是一個ACK消息,你只要不應答這個ACK,我們這個連接就建立不成,三體小說就全劇終。這就相當于三體人告訴葉教主:我活著,并且能收到你的消息,但是我還不知道你是誰,你能不能收到我這條消息。
所以第三條消息,狡猾的大劉當然不會讓三體就此game over,就是老葉告訴三體人,我也能收到你的消息,從此以后,咱們是“同志”了。
類比三次握手,和這個步驟非常相似,缺少其中任意一環,這個連接都是不可靠的,因為你不知道對方能不能收到我的消息。所以三次握手,并不是表示連接“可達”的,而是表示連接“可靠”的。這之間是有區別的,可達很簡單,UDP也能可達,一次握手也是可達的,但是并不可靠。因為無法知道這條消息對方能不能正確接收到。只有這樣反復確認后,才能表示這個連接是可靠的連接。
有杠精肯定表示不服,說理雖然是這么個理,但是會不會有巧合啊。比如某個服務既是客戶端又是服務端,我在給你發第一次握手的時候,你也恰好在給我發第一次握手,讓我誤以為你給我的消息是第二次握手的回包,從而建立了一個不可靠的連接?
而杠精之所以是杠精,就是因為木有腦子。你考慮的問題,咱們祖師爺肯定都考慮到了。
我們在前面分析三次握手的過程的時候,為什么要強調ack = 上一次的seq+1?就是代表我不僅收到了你的,我還在你的seq上加1,代表我收到的確實是你的消息,這就相當于給這條消息打上了獨一無二的標志,別人想魚目混珠都不可能。
最后,咱們說說,三體人和葉文杰建立的是TCP連接嗎?咳咳,明顯不是。本文只是舉例類比。要知道,葉文杰第一個包可是broadcast,誰都能收到的。
-
TCP
+關注
關注
8文章
1378瀏覽量
79309 -
端口
+關注
關注
4文章
990瀏覽量
32211 -
窗口
+關注
關注
0文章
66瀏覽量
10898 -
代碼
+關注
關注
30文章
4828瀏覽量
69063
發布評論請先 登錄
相關推薦
評論