建立TCP需要3次握手才能建立,而斷開連接則需要4次握手。全部進程以下圖所示:
先來看看如何建立連接的。
首先Client端發送連接要求報文,Server段接受連接后回復ACK報文,并為這次連接分配資源。Client端接收到ACK報文后也向Server段產生ACK報文,并分配資源,這樣TCP連接就建立了。
那如何斷開連接呢?簡單的進程以下:
【注意】中斷連接端可以是Client端,也能夠是Server端。
假定Client端發起中斷連接要求,也就是發送FIN報文。Server端接到FIN報文后,意思是說"我Client端沒有數據要發給你了",但是如果你還有數據沒有發送完成,則沒必要急著關閉Socket,可以繼續發送數據。所以你先發送ACK,"告知Client端,你的要求我收到了,但是我還沒準備好,請繼續你等我的消息"。這個時候Client端就進入FIN_WAIT狀態,繼續等待Server真個FIN報文。當Server端肯定數據已發送完成,則向Client端發送FIN報文,"告知Client端,好了,我這邊數據發完了,準備好關閉連接了"。Client端收到FIN報文后,"就知道可以關閉連接了,但是他還是不相信網絡,怕Server端不知道要關閉,所以發送ACK落后入TIME_WAIT狀態,如果Server端沒有收到ACK則可以重傳。“,Server端收到ACK后,"就知道可以斷開連接了"。Client端等待了2MSL后仍然沒有收到回復,則證明Server端已正常關閉,那好,我Client端也能夠關閉連接了。Ok,TCP連接就這樣關閉了!
全部進程Client端所經歷的狀態以下:
而Server端所經歷的進程以下:轉載請注明:blog.csdn.net/whuslei
【注意】 在TIME_WAIT狀態中,如果TCP client端最后1次發送的ACK丟失了,它將重新發送。TIME_WAIT狀態中所需要的時間是依賴于實現方法的。典型的值為30秒、1分鐘和2分鐘。等待以后連接正式關閉,并且所有的資源(包括端口號)都被釋放。
【問題1】為何連接的時候是3次握手,關閉的時候卻是4次握手?
答:由于當Server端收到Client真個SYN連接要求報文后,可以直接發送SYN+ACK報文。其中ACK報文是用來應對的,SYN報文是用來同步的。但是關閉連接時,當Server端收到FIN報文時,極可能其實不會立即關閉SOCKET,所以只能先回復1個ACK報文,告知Client端,"你發的FIN報文我收到了"。只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能1起發送。故需要4步握手。
【問題2】為何TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?
答:雖然按道理,4個報文都發送終了,我們可以直接進入CLOSE狀態了,但是我們必須假象網絡是不可靠的,有可以最后1個ACK丟失。所以TIME_WAIT狀態就是用來重發可能丟失的ACK報文。
TCP是面向連接的,不管哪1方向另外一方發送數據之前,都必須先在雙方之間建立1條連接。在TCP/IP協議中,TCP協議提供可靠的連接服務,連接是通過3次握手進行初始化的。3次握手的目的是同步連接雙方的序列號和確認號并交換 TCP窗口大小信息。這就是面試中常常會被問到的TCP3次握手。只是了解TCP3次握手的概念,對你取得1份工作是沒有任何幫助的,你需要去了解TCP3次握手中的1些細節。先來看圖說話。多么清晰的1張圖,固然了,也不是我畫的,我也只是援用過來講明問題了。
SYN
位置為1,Sequence
Number
為x;然后,客戶端進入SYN_SEND
狀態,等待服務器的確認;SYN
報文段。服務器收到客戶真個SYN
報文段,需要對這個SYN
報文段進行確認,設置Acknowledgment
Number
為x+1(Sequence Number
+1);同時,自己自己還要發送SYN
要求信息,將SYN
位置為1,Sequence
Number
為y;服務器端將上述所有信息放到1個報文段(即SYN+ACK
報文段)中,1并發送給客戶端,此時服務器進入SYN_RECV
狀態;SYN+ACK
報文段。然后將Acknowledgment
Number
設置為y+1,向服務器發送ACK
報文段,這個報文段發送終了以后,客戶端和服務器端都進入ESTABLISHED
狀態,完成TCP3次握手。
完成了3次握手,客戶端和服務器端就能夠開始傳送數據。以上就是TCP3次握手的整體介紹。
當客戶端和服務器通過3次握手建立了TCP連接以后,當數據傳送終了,肯定是要斷開TCP連接的啊。那對TCP的斷開連接,這里就有了神秘的“4次分手”。
Sequence Number
和Acknowledgment
Number
,向主機2發送1個FIN
報文段;此時,主機1進入FIN_WAIT_1
狀態;這表示主機1沒有數據要發送給主機2了;FIN
報文段,向主機1回1個ACK
報文段,Acknowledgment
Number
為Sequence Number
加1;主機1進入FIN_WAIT_2
狀態;主機2告知主機1,我“同意”你的關閉要求;FIN
報文段,要求關閉連接,同時主機2進入CLOSE_WAIT
狀態;FIN
報文段,向主機2發送ACK
報文段,然后主機1進入TIME_WAIT
狀態;主機2收到主機1的ACK
報文段以后,就關閉連接;此時,主機1等待2MSL后仍然沒有收到回復,則證明Server端已正常關閉,那好,主機1也能夠關閉連接了。
至此,TCP的4次分手就這么愉快的完成了。當你看到這里,你的頭腦里會有很多的疑問,很多的不懂,感覺很混亂;沒事,我們繼續總結。
既然總結了TCP的3次握手,那為何非要3次呢?怎樣覺得兩次就能夠完成了。那TCP為何非要進行3次連接呢?在謝希仁的《計算機網絡》中是這樣說的:
為了避免已失效的連接要求報文段突然又傳送到了服務端,因此產生毛病。
在書中同時舉了1個例子,以下:
“已失效的連接要求報文段”的產生在這樣1種情況下:client發出的第1個連接要求報文段并沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以后的某個時間才到達server。本來這是1個早已失效的報文段。但server收到此失效的連接要求報文段后,就誤認為是client再次發出的1個新的連接要求。因而就向client發出確認報文段,同意建立連接。假定不采取“3次握手”,那末只要server發出確認,新的連接就建立了。由于現在client并沒有發出建立連接的要求,因此不會理會server的確認,也不會向server發送數據。但server卻以為新的運輸連接已建立,并1直等待client發來數據。這樣,server的很多資源就白白浪費掉了。采取“3次握手”的辦法可以避免上述現象產生。例如剛才那種情況,client不會向server的確認發出確認。server由于收不到確認,就知道client并沒有要求建立連接。”
這就很明白了,避免了服務器真個1直等待而浪費資源。
那4次分手又是為什么呢?TCP協議是1種面向連接的、可靠的、基于字節流的運輸層通訊協議。TCP是全雙工模式,這就意味著,當主機1發出FIN
報文段時,只是表示主機1已沒有數據要發送了,主機1告知主機2,它的數據已全部發送終了了;但是,這個時候主機1還是可以接受來自主機2的數據;當主機2返回ACK
報文段時,表示它已知道主機1沒有數據發送了,但是主機2還是可以發送數據到主機1的;當主機2也發送了FIN
報文段時,這個時候就表示主機2也沒有數據要發送了,就會告知主機1,我也沒有數據要發送了,以后彼此就會愉快的中斷這次TCP連接。如果要正確的理解4次分手的原理,就需要了解4次分手進程中的狀態變化。
FIN_WAIT_1
: 這個狀態要好好解釋1下,其實FIN_WAIT_1
和FIN_WAIT_2
狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區分是:FIN_WAIT_1
狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN
報文,此時該SOCKET即進入到FIN_WAIT_1
狀態。而當對方回應ACK報文后,則進入到FIN_WAIT_2
狀態,固然在實際的正常情況下,不管對方何種情況下,都應當馬上回應ACK報文,所以FIN_WAIT_1
狀態1般是比較難見到的,而FIN_WAIT_2
狀態還有經常常可以用netstat看到。(主動方)FIN_WAIT_2
:上面已詳細解釋了這類狀態,實際上FIN_WAIT_2
狀態下的SOCKET,表示半連接,也即有1方要求close連接,但另外還告知對方,我暫時還有點數據需要傳送給你(ACK信息),稍后再關閉連接。(主動方)CLOSE_WAIT
:這類狀態的含義實際上是表示在等待關閉。怎樣理解呢?當對方close1個SOCKET后發送FIN
報文給自己,你系統毫無疑問地會回應1個ACK報文給對方,此時則進入到CLOSE_WAIT
狀態。接下來呢,實際上你真正需要斟酌的事情是觀察你是不是還有數據發送給對方,如果沒有的話,那末你也就能夠
close這個SOCKET,發送FIN
報文給對方,也即關閉連接。所以你在CLOSE_WAIT
狀態下,需要完成的事情是等待你去關閉連接。(被動方)LAST_ACK
: 這個狀態還是比較容易好理解的,它是被動關閉1方在發送FIN
報文后,最后等待對方的ACK報文。當收到ACK報文后,也便可以進入到CLOSED可用狀態了。(被動方)TIME_WAIT
: 表示收到了對方的FIN報文,并發送出了ACK報文,就等2MSL后便可回到CLOSED可用狀態了。如果FINWAIT1狀態下,收到了對方同時帶FIN標志和ACK標志的報文時,可以直接進入到TIME_WAIT
狀態,而不必經過FIN_WAIT_2
狀態。(主動方)CLOSED
: 表示連接中斷TCP(Transmission Control Protocol) 傳輸控制協議
TCP是主機對主機層的傳輸控制協議,提供可靠的連接服務,采取3次握手確認建立1個連接:
位碼即tcp標志位,有6種標示:SYN(synchronous建立聯機) ACK(acknowledgement 確認) PSH(push傳送) FIN(finish結束) RST(reset重置) URG(urgent緊急)
Sequence number(順序號碼) Acknowledge number(確認號碼)
第1次握手:主機A發送位碼為syn=1,隨機產生seq number=1234567的數據包到服務器,主機B由SYN=1知道,A要求建立聯機;
第2次握手:主機B收到要求后要確認聯機信息,向A發送ack number=(主機A的seq+1),syn=1,ack=1,隨機產生seq=7654321的包
第3次握手:主機A收到后檢查ack number是不是正確,即第1次發送的seq number+1,和位碼ack是不是為1,若正確,主機A會再發送ack number=(主機B的seq+1),ack=1,主機B收到后確認seq值與ack=1則連接建立成功。
完成3次握手,主機A與主機B開始傳送數據。
在TCP/IP協議中,TCP協議提供可靠的連接服務,采取3次握手建立1個連接。
第1次握手:建立連接時,客戶端發送syn包(syn=j)到服務器,并進入SYN_SEND狀態,等待服務器確認;
第2次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送1個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態; 第3次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送終了,客戶端和服務器進入ESTABLISHED狀態,完成3次握手。 完成3次握手,客戶端與服務器開始傳送數據.
實例:
IP 192.168.1.116.3337 > 192.168.1.123.7788: S 3626544836:3626544836
IP 192.168.1.123.7788 > 192.168.1.116.3337: S 1739326486:1739326486 ack 3626544837
IP 192.168.1.116.3337 > 192.168.1.123.7788: ack 1739326487,ack 1
第1次握手:192.168.1.116發送位碼syn=1,隨機產生seq number=3626544836的數據包到192.168.1.123,192.168.1.123由SYN=1知道192.168.1.116要求建立聯機;
第2次握手:192.168.1.123收到要求后要確認聯機信息,向192.168.1.116發送ack number=3626544837,syn=1,ack=1,隨機產生seq=1739326486的包;
第3次握手:192.168.1.116收到后檢查ack number是不是正確,即第1次發送的seq number+1,和位碼ack是不是為1,若正確,192.168.1.116會再發送ack number=1739326487,ack=1,192.168.1.123收到后確認seq=seq+1,ack=1則連接建立成功。
圖解:
1個3次握手的進程(圖1,圖2)
(圖1)
(圖2)
第1次握手的標志位(圖3)
我們可以看到標志位里面只有個同步位,也就是在做要求(SYN)
(圖3)
第2次握手的標志位(圖4)
我們可以看到標志位里面有個確認位和同步位,也就是在做應對(SYN + ACK)
(圖4)
第3次握手的標志位(圖5)
我們可以看到標志位里面只有個確認位,也就是再做再次確認(ACK)
TCP頭部: 其中 ACK SYN 序號 這3個部份在以下會用到,它們的介紹也在下面。
暫時需要的信息有:
ACK : TCP協議規定,只有ACK=1時有效,也規定連接建立后所有發送的報文的ACK必須為1
SYN(SYNchronization) : 在連接建立時用來同步序號。當SYN=1而ACK=0時,表明這是1個連接要求報文。對方若同意建立連接,則應在響應報文中使SYN=1和ACK=1. 因此, SYN置1就表示這是1個連接要求或連接接受報文。
FIN (finis)即完,終結的意思, 用來釋放1個連接。當 FIN = 1 時,表明此報文段的發送方的數據已發送終了,并要求釋放連接。
3次握手的進程:
首先由Client發出要求連接即 SYN=1 ACK=0 (請看頭字段的介紹), TCP規定SYN=1時不能攜帶數據,但要消耗1個序號,因此聲明自己的序號是 seq=x
然后 Server 進行回復確認,即 SYN=1 ACK=1 seq=y, ack=x+1,
再然后 Client 再進行1次確認,但不用SYN 了,這時候即為 ACK=1, seq=x+1, ack=y+1.
然后連接建立,為何要進行3次握手呢(兩次確認)。
下面是釋放連接的進程:
當客戶A 沒有東西要發送時就要釋放 A 這邊的連接,A會發送1個報文(沒有數據),其中 FIN 設置為1, 服務器B收到后會給利用程序1個信,這時候A那邊的連接已關閉,即A不再發送信息(但仍可接收信息)。 A收到B的確認落后入等待狀態,等待B要求釋放連接, B數據發送完成后就向A要求連接釋放,也是用FIN=1 表示, 并且用 ack = u+1(如圖), A收到后回復1個確認信息,并進入 TIME_WAIT 狀態, 等待 2MSL 時間。
為何要等待呢?
為了這類情況: B向A發送 FIN = 1 的釋放連接要求,但這個報文丟失了, A沒有接到不會發送確認信息, B 超時會重傳,這時候A在 WAIT_TIME 還能夠接收到這個要求,這時候再回復1個確認就好了。(A收到 FIN = 1 的要求后 WAIT_TIME會重新記時)
另外服務器B存在1個保活狀態,即如果A突然故障死機了,那B那邊的連接資源甚么時候能釋放呢? 就是保活時間到了后,B會發送探測信息, 以決定是不是釋放連接。