TCP的三次握手四次揮手

1. TCP協(xié)議的三次握手

參考網(wǎng)站
TCP(Transmission Control Protocol,傳輸控制協(xié)議)是面向連接的協(xié)議,也就是說,在收發(fā)數(shù)據(jù)前,必須和對方建立可靠的連接。
一個TCP連接必須要經(jīng)過三次“對話”才能建立起來,其中的過程非常復雜,只簡單的描述下這三次對話的簡單過程:主機A向主機B發(fā)出連接請求數(shù)據(jù)包:“我想給你發(fā)數(shù)據(jù),可以嗎?”,這是第一次對話;主機B向主機A發(fā)送同意連接和要求同步(同步就是兩臺主機一個在發(fā)送,一個在接收,協(xié)調工作)的數(shù)據(jù)包:“可以,你什么時候發(fā)?”,這是第二次對話;主機A再發(fā)出一個數(shù)據(jù)包確認主機B的要求同步:“我現(xiàn)在就發(fā),你接著吧!”,這是第三次對話。三次“對話”的目的是使數(shù)據(jù)包的發(fā)送和接收同步,經(jīng)過三次“對話”之后,主機A才向主機B正式發(fā)送數(shù)據(jù)。

TCP協(xié)議的三次握手動態(tài)圖

1、TCP服務器進程先創(chuàng)建傳輸控制塊TCB,時刻準備接受客戶進程的連接請求,此時服務器就進入了LISTEN(監(jiān)聽)狀態(tài);
2、TCP客戶進程也是先創(chuàng)建傳輸控制塊TCB,然后向服務器發(fā)出連接請求報文,這是報文首部中的同步位SYN=1,同時選擇一個初始序列號 seq=x ,此時,TCP客戶端進程進入了 SYN-SENT(同步已發(fā)送狀態(tài))狀態(tài)。TCP規(guī)定,SYN報文段(SYN=1的報文段)不能攜帶數(shù)據(jù),但需要消耗掉一個序號。
3、TCP服務器收到請求報文后,如果同意連接,則發(fā)出確認報文。確認報文中應該 ACK=1,SYN=1,確認號是ack=x+1,同時也要為自己初始化一個序列號 seq=y,此時,TCP服務器進程進入了SYN-RCVD(同步收到)狀態(tài)。這個報文也不能攜帶數(shù)據(jù),但是同樣要消耗一個序號。
4、TCP客戶進程收到確認后,還要向服務器給出確認。確認報文的ACK=1,ack=y+1,自己的序列號seq=x+1,此時,TCP連接建立,客戶端進入ESTABLISHED(已建立連接)狀態(tài)。TCP規(guī)定,ACK報文段可以攜帶數(shù)據(jù),但是如果不攜帶數(shù)據(jù)則不消耗序號(就沒有seq=x+1)。
5、當服務器收到客戶端的確認后也進入ESTABLISHED狀態(tài),此后雙方就可以開始通信了。

TCP協(xié)議的三次握手

(其中大寫的字母表示狀態(tài)位,小寫字母表示序號,ack表示相應的序號,seq表示報文的序號;)
1、確認位ACK,僅當ACK=1時,確認號字段才有效。TCP規(guī)定,在連接建立后所有報文的傳輸都必須把ACK置1;
2、同步位SYN,在連接建立時用來同步序號。當SYN=1,ACK=0,表明是連接請求報文,若同意連接,則響應報文中應該使SYN=1,ACK=1;

為什么TCP客戶端最后還要發(fā)送一次確認呢?

已失效的連接請求報文段”的產(chǎn)生在這樣一種情況下: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并沒有要求建立連接。

2.TCP的四次揮手

數(shù)據(jù)傳輸完畢后,雙方都可釋放連接。最開始的時候,客戶端和服務器都是處于ESTABLISHED狀態(tài),然后客戶端主動關閉,服務器被動關閉。


TCP四次揮手動態(tài)圖

1、客戶端進程發(fā)出連接釋放報文,并且停止發(fā)送數(shù)據(jù)。釋放數(shù)據(jù)報文首部,F(xiàn)IN=1,其序列號為seq=u(等于前面已經(jīng)傳送過來的數(shù)據(jù)的最后一個字節(jié)的序號加1),此時,客戶端進入FIN-WAIT-1(終止等待1)狀態(tài)。 TCP規(guī)定,F(xiàn)IN報文段即使不攜帶數(shù)據(jù),也要消耗一個序號。
2、服務器收到連接釋放報文,發(fā)出確認報文,ACK=1,ack=u+1,并且?guī)献约旱男蛄刑杝eq=v,此時,服務端就進入了CLOSE-WAIT(關閉等待)狀態(tài)。TCP服務器通知高層的應用進程,客戶端向服務器的方向就釋放了,這時候處于半關閉狀態(tài),即客戶端已經(jīng)沒有數(shù)據(jù)要發(fā)送了,但是服務器若發(fā)送數(shù)據(jù),客戶端依然要接受。這個狀態(tài)還要持續(xù)一段時間,也就是整個CLOSE-WAIT狀態(tài)持續(xù)的時間。
3、客戶端收到服務器的確認請求后,此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態(tài),等待服務器發(fā)送連接釋放報文(在這之前還需要接受服務器發(fā)送的最后的數(shù)據(jù))。
4、服務器將最后的數(shù)據(jù)發(fā)送完畢后,就向客戶端發(fā)送連接釋放報文,F(xiàn)IN=1,ack=u+1,由于在半關閉狀態(tài),服務器很可能又發(fā)送了一些數(shù)據(jù),假定此時的序列號為seq=w,此時,服務器就進入了LAST-ACK(最后確認)狀態(tài),等待客戶端的確認。
5、客戶端收到服務器的連接釋放報文后,必須發(fā)出確認,ACK=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態(tài)。注意此時TCP連接還沒有釋放,必須經(jīng)過2? *?MSL(最長報文段壽命)的時間后,當客戶端撤銷相應的TCB后,才進入CLOSED狀態(tài)。
6、服務器只要收到了客戶端發(fā)出的確認,立即進入CLOSED狀態(tài)。同樣,撤銷TCB后,就結束了這次的TCP連接。可以看到,服務器結束TCP連接的時間要比客戶端早一些。

TCP的四次揮手

為什么客戶端最后還要等待2MSL?

MSL(Maximum Segment Lifetime),TCP允許不同的實現(xiàn)可以設置不同的MSL值。

第一,保證客戶端發(fā)送的最后一個ACK報文能夠到達服務器,因為這個ACK報文可能丟失,站在服務器的角度看來,我已經(jīng)發(fā)送了FIN+ACK報文請求斷開了,客戶端還沒有給我回應,應該是我發(fā)送的請求斷開報文它沒有收到,于是服務器又會重新發(fā)送一次,而客戶端就能在這個2MSL時間段內收到這個重傳的報文,接著給出回應報文,并且會重啟2MSL計時器。

第二,防止類似與“三次握手”中提到了的“已經(jīng)失效的連接請求報文段”出現(xiàn)在本連接中??蛻舳税l(fā)送完最后一個確認報文后,在這個2MSL時間中,就可以使本連接持續(xù)的時間內所產(chǎn)生的所有報文段都從網(wǎng)絡中消失。這樣新的連接中不會出現(xiàn)舊連接的請求報文。

原因有二:
一、保證TCP協(xié)議的全雙工連接能夠可靠關閉
二、保證這次連接的重復數(shù)據(jù)段從網(wǎng)絡中消失

  • 先說第一點,如果Client直接CLOSED了,那么由于IP協(xié)議的不可靠性或者是其它網(wǎng)絡原因,導致Server沒有收到Client最后回復的ACK。那么Server就會在超時之后繼續(xù)發(fā)送FIN,此時由于Client已經(jīng)CLOSED了,就找不到與重發(fā)的FIN對應的連接,最后Server就會收到RST而不是ACK,Server就會以為是連接錯誤把問題報告給高層。這樣的情況雖然不會造成數(shù)據(jù)丟失,但是卻導致TCP協(xié)議不符合可靠連接的要求。所以,Client不是直接進入CLOSED,而是要保持TIME_WAIT,當再次收到FIN的時候,能夠保證對方收到ACK,最后正確的關閉連接。

  • 再說第二點,如果Client直接CLOSED,然后又再向Server發(fā)起一個新連接,我們不能保證這個新連接與剛關閉的連接的端口號是不同的。也就是說有可能新連接和老連接的端口號是相同的。一般來說不會發(fā)生什么問題,但是還是有特殊情況出現(xiàn):假設新連接和已經(jīng)關閉的老連接端口號是一樣的,如果前一次連接的某些數(shù)據(jù)仍然滯留在網(wǎng)絡中,這些延遲數(shù)據(jù)在建立新連接之后才到達Server,由于新連接和老連接的端口號是一樣的,又因為TCP協(xié)議判斷不同連接的依據(jù)是socket pair,于是,TCP協(xié)議就認為那個延遲的數(shù)據(jù)是屬于新連接的,這樣就和真正的新連接的數(shù)據(jù)包發(fā)生混淆了。所以TCP連接還要在TIME_WAIT狀態(tài)等待2倍MSL,這樣可以保證本次連接的所有數(shù)據(jù)都從網(wǎng)絡中消失。

為什么建立連接是三次握手,關閉連接確是四次揮手呢?

建立連接的時候, 服務器在LISTEN狀態(tài)下,收到建立連接請求的SYN報文后,把ACK和SYN放在一個報文里發(fā)送給客戶端。
而關閉連接時,服務器收到對方的FIN報文時,僅僅表示對方不再發(fā)送數(shù)據(jù)了但是還能接收數(shù)據(jù),而自己也未必全部數(shù)據(jù)都發(fā)送給對方了,所以己方可以立即關閉,也可以發(fā)送一些數(shù)據(jù)給對方后,再發(fā)送FIN報文給對方來表示同意現(xiàn)在關閉連接,因此,己方ACK和FIN一般都會分開發(fā)送,從而導致多了一次。

如果已經(jīng)建立了連接,但是客戶端突然出現(xiàn)故障了怎么辦?

TCP還設有一個?;钣嫊r器,顯然,客戶端如果出現(xiàn)故障,服務器不能一直等下去,白白浪費資源。服務器每收到一次客戶端的請求后都會重新復位這個計時器,時間通常是設置為2小時,若兩小時還沒有收到客戶端的任何數(shù)據(jù),服務器就會發(fā)送一個探測報文段,以后每隔75秒發(fā)送一次。若一連發(fā)送10個探測報文仍然沒反應,服務器就認為客戶端出了故障,接著就關閉連接。

四次揮手中主動斷開鏈接的一方為什么要進入TIME_WAIT狀態(tài) ?

TCP連接是全雙工通信,斷開連接的主動方和被動方都需要自主關閉通信鏈路,TCP正常情況下連接斷開會進行四次揮手:
1.由主動斷開方發(fā)起FIN
2.被動方回復ACK
3.待被動方數(shù)據(jù)傳輸完成,被動方發(fā)送FIN
4.主動方回復ACK,并進入TIME_WAIT狀態(tài)

因為TCP是建立在非連接鏈路的可靠傳輸通信方式,在TCP連接中,當被動方發(fā)送的FIN報文到達時,主動方會發(fā)送ACK確認報文,并且進入TIME_WAIT狀態(tài),TIME_WAIT的狀態(tài)會持續(xù)2MSL (MSL是報文在網(wǎng)絡中生存的最大生命周期)。那這里主動發(fā)送方為什么要進入TIME_WAIT狀態(tài),并且TIME_WAIT狀態(tài)為什么需要2MSL的狀態(tài)?

有下述兩個原因:

  1. 若在第四次揮手時發(fā)出ACK確認應答時,由于網(wǎng)絡原因導致ACK確認應答的報文沒有被被動方收到,等到2MSL從而觸發(fā)被動方重新發(fā)送FIN包,因而主動關閉連接的一方需要停留在TIME_WAIT等待狀態(tài)以處理對方重新發(fā)送的FIN數(shù)據(jù)包。否則它會回應一個RST數(shù)據(jù)包給被動關閉連接的一方,引起被動方關閉流程錯亂。

2.在TIME_WAIT狀態(tài)下,是不允許應用程序在當前ip和端口上與之前通信的client(這個client的ip和端口號不變)建立一個新的連接的。這樣就能避免新連接收到之前的連接(ip和端口一致的連接)殘存在網(wǎng)絡中的數(shù)據(jù)包了。這也是TIME_WAIT狀態(tài)的等待時間被設置為2MSL的原因,以確保當前網(wǎng)絡兩個連接方向上的尚未接收到的TCP報文已經(jīng)全部消失 。


TCP的狀態(tài)轉移


TCP/IP報文頭部結構

1、IP

IP協(xié)議是TCP/IP協(xié)議族的動力,它為上層協(xié)議提供無狀態(tài)、無連接、不可靠的服務。

  • 優(yōu)點:簡單,高效。

  • 無狀態(tài):IP通信雙方不同步傳輸數(shù)據(jù)的狀態(tài)信息,所有的IP數(shù)據(jù)報的傳輸都是獨立的。所以容易發(fā)生重復和亂序的情況并且IP層不予處理。 然后將這些亂序的交給上層傳輸層(TCP/UDP等)來處理,將其處理成有序的,正確的。再交給應用層。

  • 不可靠:IP協(xié)議不能保證IP數(shù)據(jù)報準確到達。所以它提供ICMP報文來輔助,一旦檢測到IP數(shù)據(jù)報發(fā)送失敗,通知上層協(xié)議。

IP頭部信息:
頭部長度:通常20字節(jié),有選項時更長,總共不超過60字節(jié)。
IP數(shù)據(jù)報長度:65535字節(jié)。
逐個分析:

  • 4位版本號:IP協(xié)議(IPv4)版本號位4

  • 4位頭部長度:標識頭部有多少個4字節(jié),即最大共15*4個字節(jié)

  • 8位服務類型:包含一個4位優(yōu)先權字段:最小延時,最大吞吐量,最高可靠性和最小費用。

  • 16位總長度:表示整個IP數(shù)據(jù)報的長度,最大表示65535,但由于MTU限制,一般無法到達這個值。

  • 16位標識:唯一的標識數(shù)據(jù)報。系統(tǒng)采用加1的式邊發(fā)送邊賦值。

  • 3位標識(保留,DF禁止分片,MF更多分片):所以這個標志是為分片存在,DF設置時禁止分片所以如果數(shù)據(jù)報太大則發(fā)送失敗。MF設置時,如果產(chǎn)生分片,除了最后一個分片,其他此片置1。

  • 13位分片偏移:分片相對原始IP數(shù)據(jù)報開始處的偏移。

  • 8位生存時間(TTL):數(shù)據(jù)報到達目的地之前允許經(jīng)過的路由跳跳數(shù)。跳一下減1,得0丟棄。

  • 8位協(xié)議:用來區(qū)分上層協(xié)議(ICMP為1,TCP為6,UDP為17)。

  • 16位頭部校驗和:僅以CRC算法檢驗數(shù)據(jù)報頭部在傳輸過程中是否損壞。

  • 32位源端口IP地址和目的端口地址很明白。

  • 選項(可變長):記錄路由,告訴途徑得所有路由把IP填進來。 時間戳,告訴每個路由器都將數(shù)據(jù)報被轉發(fā)的時間傳進來。松散路由選擇,指定一個路由器IP地址列表,必須按這個表發(fā)送,嚴格路由選擇,數(shù)據(jù)報經(jīng)過路由表。

2、TCP報文結構

特點:可靠性。通過連接管理(三握四揮),序列號,確認號,擁塞控制,重傳控制來保證可靠性。
頭部長度:一般為20字節(jié),選項最多40字節(jié),限制60字節(jié)。



逐個分析:

  • 16位源端口號和16位目的端口號。

  • 32位序號:一次TCP通信過程中某一個傳輸方向上的字節(jié)流的每個字節(jié)的編號,通過這個來確認發(fā)送的數(shù)據(jù)有序,比如現(xiàn)在序列號為1000,發(fā)送了1000,下一個序列號就是2000。

  • 32位確認號:用來響應TCP報文段,給收到的TCP報文段的序號加1,三握時還要攜帶自己的序號。

  • 4位頭部長度:標識該TCP頭部有多少個4字節(jié),共表示最長15*4=60字節(jié)。同IP頭部。

  • 6位保留。6位標志。URG(緊急指針是否有效)ACK(表示確認號是否有效)PSH(提示接收端應用程序應該立即從TCP接收緩沖區(qū)讀走數(shù)據(jù))RST(表示要求對方重新建立連接)SYN(表示請求建立一個連接)FIN(表示通知對方本端要關閉連接)

  • 16位窗口大?。篢CP流量控制的一個手段,用來告訴對端TCP緩沖區(qū)還能容納多少字節(jié)。

  • 16位校驗和:由發(fā)送端填充,接收端對報文段執(zhí)行CRC算法以檢驗TCP報文段在傳輸中是否損壞。

  • 16位緊急指針:一個正的偏移量,它和序號段的值相加表示最后一個緊急數(shù)據(jù)的下一字節(jié)的序號。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容