一文徹底搞懂 TCP三次握手围详、四次揮手過程及原理

TCP 協(xié)議簡述

TCP 提供面向有連接的通信傳輸朴乖,面向有連接是指在傳送數(shù)據(jù)之前必須先建立連接,數(shù)據(jù)傳送完成后要釋放連接短曾。

無論哪一方向另一方發(fā)送數(shù)據(jù)之前,都必須先在雙方之間建立一條連接赐劣。在TCP/IP協(xié)議中嫉拐,TCP協(xié)議提供可靠的連接服務,連接是通過三次握手進行初始化的魁兼。
同時由于TCP協(xié)議是一種面向連接的婉徘、可靠的漠嵌、基于字節(jié)流的運輸層通信協(xié)議,TCP是全雙工模式盖呼,所以需要四次揮手關閉連接儒鹿。

TCP包首部

網(wǎng)絡中傳輸?shù)臄?shù)據(jù)包由兩部分組成:一部分是協(xié)議所要用到的首部,另一部分是上一層傳過來的數(shù)據(jù)几晤。首部的結構由協(xié)議的具體規(guī)范詳細定義约炎。在數(shù)據(jù)包的首部,明確標明了協(xié)議應該如何讀取數(shù)據(jù)蟹瘾。反過來說圾浅,看到首部,也就能夠了解該協(xié)議必要的信息以及所要處理的數(shù)據(jù)憾朴。包首部就像協(xié)議的臉狸捕。

所以我們在學習TCP協(xié)議之前,首先要知道TCP在網(wǎng)絡傳輸中處于哪個位置众雷,以及它的協(xié)議的規(guī)范灸拍,下面我們就看看TCP首部的網(wǎng)絡傳輸起到的作用:

網(wǎng)絡數(shù)據(jù)傳輸過程

下面的圖是TCP頭部的規(guī)范定義,它定義了TCP協(xié)議如何讀取和解析數(shù)據(jù):


TCP頭部

TCP首部承載這TCP協(xié)議需要的各項信息砾省,下面我們來分析一下:

  • TCP端口號
    TCP的連接是需要四個要素確定唯一一個連接:
    (源IP鸡岗,源端口號)+ (目地IP,目的端口號)
    所以TCP首部預留了兩個16位作為端口號的存儲纯蛾,而IP地址由上一層IP協(xié)議負責傳遞
    源端口號和目地端口各占16位兩個字節(jié)纤房,也就是端口的范圍是2^16=65535
    另外1024以下是系統(tǒng)保留的,從1024-65535是用戶使用的端口范圍

  • TCP的序號和確認號
    32位序號 seq:Sequence number 縮寫seq 翻诉,TCP通信過程中某一個傳輸方向上的字節(jié)流的每個字節(jié)的序號炮姨,通過這個來確認發(fā)送的數(shù)據(jù)有序,比如現(xiàn)在序列號為1000碰煌,發(fā)送了1000舒岸,下一個序列號就是2000。
    32位確認號 ack:Acknowledge number 縮寫ack芦圾,TCP對上一次seq序號做出的確認號蛾派,用來響應TCP報文段,給收到的TCP報文段的序號seq加1个少。

  • TCP的標志位
    每個TCP段都有一個目的洪乍,這是借助于TCP標志位選項來確定的,允許發(fā)送方或接收方指定哪些標志應該被使用夜焦,以便段被另一端正確處理壳澳。
    用的最廣泛的標志是 SYNACKFIN茫经,用于建立連接巷波,確認成功的段傳輸萎津,最后終止連接。

    1. SYN:簡寫為S抹镊,同步標志位锉屈,用于建立會話連接,同步序列號垮耳;
    2. ACK: 簡寫為.颈渊,確認標志位,對已接收的數(shù)據(jù)包進行確認氨菇;
    3. FIN: 簡寫為F儡炼,完成標志位,表示我已經(jīng)沒有數(shù)據(jù)要發(fā)送了查蓉,即將關閉連接乌询;
    4. PSH:簡寫為P,推送標志位豌研,表示該數(shù)據(jù)包被對方接收后應立即交給上層應用妹田,而不在緩沖區(qū)排隊;
    5. RST:簡寫為R鹃共,重置標志位鬼佣,用于連接復位、拒絕錯誤和非法的數(shù)據(jù)包霜浴;
    6. URG:簡寫為U晶衷,緊急標志位,表示數(shù)據(jù)包的緊急指針域有效阴孟,用來保證連接不被阻斷晌纫,并督促中間設備盡快處理;

TCP 三次握手建立連接

所謂三次握手(Three-way Handshake)永丝,是指建立一個 TCP 連接時锹漱,需要客戶端和服務器總共發(fā)送3個報文。

三次握手的目的是連接服務器指定端口慕嚷,建立 TCP 連接哥牍,并同步連接雙方的序列號和確認號,交換 TCP 窗口大小信息喝检。在 socket 編程中嗅辣,客戶端執(zhí)行 connect() 時。將觸發(fā)三次握手挠说。

三次握手過程的示意圖如下:


三次握手建立連接
  • 第一次握手
    客戶端將TCP報文標志位SYN置為1澡谭,隨機產生一個序號值seq=J,保存在TCP首部的序列號(Sequence Number)字段里纺涤,指明客戶端打算連接的服務器的端口译暂,并將該數(shù)據(jù)包發(fā)送給服務器端,發(fā)送完畢后撩炊,客戶端進入SYN_SENT狀態(tài)外永,等待服務器端確認。

  • 第二次握手
    服務器端收到數(shù)據(jù)包后由標志位SYN=1知道客戶端請求建立連接拧咳,服務器端將TCP報文標志位SYN和ACK都置為1伯顶,ack=J+1,隨機產生一個序號值seq=K骆膝,并將該數(shù)據(jù)包發(fā)送給客戶端以確認連接請求祭衩,服務器端進入SYN_RCVD狀態(tài)。

  • 第三次握手
    客戶端收到確認后阅签,檢查ack是否為J+1掐暮,ACK是否為1,如果正確則將標志位ACK置為1政钟,ack=K+1路克,并將該數(shù)據(jù)包發(fā)送給服務器端,服務器端檢查ack是否為K+1估脆,ACK是否為1牢硅,如果正確則連接建立成功线欲,客戶端和服務器端進入ESTABLISHED狀態(tài),完成三次握手灰羽,隨后客戶端與服務器端之間可以開始傳輸數(shù)據(jù)了。

注意:我們上面寫的ack和ACK鱼辙,不是同一個概念:

  • 小寫的ack代表的是頭部的確認號Acknowledge number廉嚼, 縮寫ack,是對上一個包的序號進行確認的號座每,ack=seq+1前鹅。
  • 大寫的ACK,則是我們上面說的TCP首部的標志位峭梳,用于標志的TCP包是否對上一個包進行了確認操作舰绘,如果確認了,則把ACK標志位設置成1葱椭。

下面我自己做實驗捂寿,開一個HTTP服務,監(jiān)聽80端口孵运,然后使用Tcpdump命令抓包秦陋,看一下TCP三次握手的過程:

sudo tcpdump -n -t -S -i enp0s3  port 80 

第一次握手,標志位Flags=S
IP 10.0.2.2.51323 > 10.0.2.15.80: Flags [S], seq 84689409, win 65535, options [mss 1460], length 0
第二次握手治笨,標志位Flags=[S.]
IP 10.0.2.15.80 > 10.0.2.2.51323: Flags [S.], seq 1893430205, ack 84689410, win 64240, options [mss 1460], length 0
第三次握手驳概,標志位Flags=[.]
IP 10.0.2.2.51323 > 10.0.2.15.80: Flags [.], ack 1893430206, win 65535, length 0
建立連接后赤嚼,客戶端發(fā)送http請求 
IP 10.0.2.2.51321 > 10.0.2.15.80: Flags [P.], seq 1:753, ack 1, win 65535, length 752: HTTP: GET / HTTP/1.1

tcpdump命令解析一下:
-i : 指定抓包的網(wǎng)卡是enp0s3
-n: 把域名轉成IP顯示
-t: 不顯示時間
-S: 序列號使用絕對數(shù)值,不指定-S的話顺又,序列號會使用相對的數(shù)值
port: 指定監(jiān)聽端口是80
host:指定監(jiān)聽的主機名

我們看下實戰(zhàn)中TCP的三次握手過程:

  • 第一次握手更卒,客戶端51323端口號向服務器端80號端口發(fā)起連接,此時標志位flags=S稚照,即SYN=1標志蹂空,表示向服務端發(fā)起連接的請求,同時生成序列號seq=84689409
  • 第二次握手果录,服務端標志位flags=[S.]上枕,即SYN+ACK標志位設置為1,表示對上一個請求連接的報文進行確認弱恒,同時設置ack=seq+1=184689410辨萍,生成序列號seq=1893430205
  • 第三次握手,客戶端對服務端的響應進行確認返弹,所以此時標志位是[.]即ACK=1分瘦,同時返回對上一個報文的seq的確認號,ack=1893430206

至此琉苇,三次握手完成嘲玫,一個TCP連接建立完成,接下來就是雙端傳輸數(shù)據(jù)了

為什么需要三次握手并扇?

我們假設client發(fā)出的第一個連接請求報文段并沒有丟失去团,而是在某個網(wǎng)絡結點長時間的滯留了,以致延誤到連接釋放以后的某個時間才到達server穷蛹。

本來這是一個早已失效的報文段土陪。但server收到此失效的連接請求報文段后,就誤認為是client再次發(fā)出的一個新的連接請求肴熏。于是就向client發(fā)出確認報文段鬼雀,同意建立連接。

假設不采用“三次握手”蛙吏,那么只要server發(fā)出確認源哩,新的連接就建立了。由于現(xiàn)在client并沒有發(fā)出建立連接的請求鸦做,因此不會理睬server的確認励烦,也不會向server發(fā)送數(shù)據(jù)。但server卻以為新的運輸連接已經(jīng)建立泼诱,并一直等待client發(fā)來數(shù)據(jù)坛掠。這樣,server的很多資源就白白浪費掉了。

所以屉栓,采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生舷蒲。例如剛才那種情況,client不會向server的確認發(fā)出確認友多。server由于收不到確認阿纤,就知道client并沒有要求建立連接。

TCP 三次握手跟現(xiàn)實生活中的人與人打電話是很類似的:

三次握手:
“喂夷陋,你聽得到嗎?”
“我聽得到呀胰锌,你聽得到我嗎骗绕?”
“我能聽到你,今天 balabala……”

經(jīng)過三次的互相確認资昧,大家就會認為對方對聽的到自己說話酬土,并且愿意下一步溝通,否則格带,對話就不一定能正常下去了撤缴。

TCP 四次揮手關閉連接

四次揮手即終止TCP連接,就是指斷開一個TCP連接時叽唱,需要客戶端和服務端總共發(fā)送4個包以確認連接的斷開屈呕。在socket編程中,這一過程由客戶端或服務端任一方執(zhí)行close來觸發(fā)棺亭。
由于TCP連接是全雙工的虎眨,因此,每個方向都必須要單獨進行關閉镶摘,這一原則是當一方完成數(shù)據(jù)發(fā)送任務后嗽桩,發(fā)送一個FIN來終止這一方向的連接,收到一個FIN只是意味著這一方向上沒有數(shù)據(jù)流動了凄敢,即不會再收到數(shù)據(jù)了碌冶,但是在這個TCP連接上仍然能夠發(fā)送數(shù)據(jù),直到這一方向也發(fā)送了FIN涝缝。首先進行關閉的一方將執(zhí)行主動關閉扑庞,而另一方則執(zhí)行被動關閉。

四次揮手過程的示意圖如下:


四次揮手關閉連接

揮手請求可以是Client端拒逮,也可以是Server端發(fā)起的嫩挤,我們假設是Client端發(fā)起:

  • 第一次揮手: Client端發(fā)起揮手請求,向Server端發(fā)送標志位是FIN報文段消恍,設置序列號seq岂昭,此時,Client端進入FIN_WAIT_1狀態(tài),這表示Client端沒有數(shù)據(jù)要發(fā)送給Server端了约啊。
  • 第二次分手:Server端收到了Client端發(fā)送的FIN報文段邑遏,向Client端返回一個標志位是ACK的報文段,ack設為seq加1恰矩,Client端進入FIN_WAIT_2狀態(tài)记盒,Server端告訴Client端,我確認并同意你的關閉請求外傅。
  • 第三次分手: Server端向Client端發(fā)送標志位是FIN的報文段纪吮,請求關閉連接,同時Client端進入LAST_ACK狀態(tài)萎胰。
  • 第四次分手 : Client端收到Server端發(fā)送的FIN報文段碾盟,向Server端發(fā)送標志位是ACK的報文段,然后Client端進入TIME_WAIT狀態(tài)技竟。Server端收到Client端的ACK報文段以后冰肴,就關閉連接。此時榔组,Client端等待2MSL的時間后依然沒有收到回復熙尉,則證明Server端已正常關閉,那好搓扯,Client端也可以關閉連接了检痰。

為什么連接的時候是三次握手,關閉的時候卻是四次握手锨推?

建立連接時因為當Server端收到Client端的SYN連接請求報文后攀细,可以直接發(fā)送SYN+ACK報文。其中ACK報文是用來應答的爱态,SYN報文是用來同步的谭贪。所以建立連接只需要三次握手。

由于TCP協(xié)議是一種面向連接的锦担、可靠的俭识、基于字節(jié)流的運輸層通信協(xié)議,TCP是全雙工模式洞渔。
這就意味著套媚,關閉連接時,當Client端發(fā)出FIN報文段時磁椒,只是表示Client端告訴Server端數(shù)據(jù)已經(jīng)發(fā)送完畢了堤瘤。當Server端收到FIN報文并返回ACK報文段,表示它已經(jīng)知道Client端沒有數(shù)據(jù)發(fā)送了浆熔,但是Server端還是可以發(fā)送數(shù)據(jù)到Client端的本辐,所以Server很可能并不會立即關閉SOCKET,直到Server端把數(shù)據(jù)也發(fā)送完畢。
當Server端也發(fā)送了FIN報文段時慎皱,這個時候就表示Server端也沒有數(shù)據(jù)要發(fā)送了老虫,就會告訴Client端,我也沒有數(shù)據(jù)要發(fā)送了茫多,之后彼此就會愉快的中斷這次TCP連接祈匙。

為什么要等待2MSL?

MSL:報文段最大生存時間天揖,它是任何報文段被丟棄前在網(wǎng)絡內的最長時間夺欲。
有以下兩個原因:

  • 第一點:保證TCP協(xié)議的全雙工連接能夠可靠關閉
    由于IP協(xié)議的不可靠性或者是其它網(wǎng)絡原因,導致了Server端沒有收到Client端的ACK報文今膊,那么Server端就會在超時之后重新發(fā)送FIN些阅,如果此時Client端的連接已經(jīng)關閉處于CLOESD狀態(tài),那么重發(fā)的FIN就找不到對應的連接了万细,從而導致連接錯亂,所以纸泄,Client端發(fā)送完最后的ACK不能直接進入CLOSED狀態(tài)赖钞,而要保持TIME_WAIT,當再次收到FIN的收聘裁,能夠保證對方收到ACK雪营,最后正確關閉連接。
  • 第二點:保證這次連接的重復數(shù)據(jù)段從網(wǎng)絡中消失
    如果Client端發(fā)送最后的ACK直接進入CLOSED狀態(tài)衡便,然后又再向Server端發(fā)起一個新連接献起,這時不能保證新連接的與剛關閉的連接的端口號是不同的,也就是新連接和老連接的端口號可能一樣了镣陕,那么就可能出現(xiàn)問題:如果前一次的連接某些數(shù)據(jù)滯留在網(wǎng)絡中谴餐,這些延遲數(shù)據(jù)在建立新連接后到達Client端,由于新老連接的端口號和IP都一樣呆抑,TCP協(xié)議就認為延遲數(shù)據(jù)是屬于新連接的岂嗓,新連接就會接收到臟數(shù)據(jù),這樣就會導致數(shù)據(jù)包混亂鹊碍。所以TCP連接需要在TIME_WAIT狀態(tài)等待2倍MSL厌殉,才能保證本次連接的所有數(shù)據(jù)在網(wǎng)絡中消失。

出處:https://www.cnblogs.com/onesea/p/13053697.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末侈咕,一起剝皮案震驚了整個濱河市公罕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌耀销,老刑警劉巖楼眷,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡摩桶,警方通過查閱死者的電腦和手機桥状,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來硝清,“玉大人辅斟,你說我怎么就攤上這事÷茫” “怎么了士飒?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蔗崎。 經(jīng)常有香客問我酵幕,道長,這世上最難降的妖魔是什么缓苛? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任芳撒,我火速辦了婚禮,結果婚禮上未桥,老公的妹妹穿的比我還像新娘笔刹。我一直安慰自己,他們只是感情好冬耿,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布舌菜。 她就那樣靜靜地躺著,像睡著了一般亦镶。 火紅的嫁衣襯著肌膚如雪日月。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天缤骨,我揣著相機與錄音爱咬,去河邊找鬼。 笑死绊起,一個胖子當著我的面吹牛台颠,可吹牛的內容都是我干的。 我是一名探鬼主播勒庄,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼串前,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了实蔽?” 一聲冷哼從身側響起荡碾,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎局装,沒想到半個月后坛吁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體劳殖,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年拨脉,在試婚紗的時候發(fā)現(xiàn)自己被綠了哆姻。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡玫膀,死狀恐怖矛缨,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情帖旨,我是刑警寧澤箕昭,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站解阅,受9級特大地震影響落竹,放射性物質發(fā)生泄漏。R本人自食惡果不足惜货抄,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一述召、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蟹地,春花似錦积暖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凉蜂。三九已至琼梆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窿吩,已是汗流浹背茎杂。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留纫雁,地道東北人煌往。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像轧邪,于是被迫代替她去往敵國和親刽脖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345