InterV 8:通訊協(xié)議
一、三次握手簡單例子
A:客戶端 B:服務(wù)端
第一次握手: A給B打電話說,你可以聽到我說話嗎?
第二次握手: B收到了A的信息,然后對A說: 我可以聽得到你說話啊,你能聽得到我說話嗎?
第三次握手: A收到了B的信息,然后說我能聽到你說話,我要給你發(fā)信息啦!
圖文說明:

第一次握手:客戶端通過調(diào)用connect發(fā)起主動打開。客戶端向服務(wù)器發(fā)出連接請求的TCP報文段,其TCP首部中的同步比特SYN置為1,并TCP首部中序號seq設(shè)置為x(TCP規(guī)定SYN報文段不能攜帶數(shù)據(jù),但是要消耗一個序號),表明要轉(zhuǎn)送數(shù)據(jù)時初始序列號是x。
第二次握手:服務(wù)器收到數(shù)據(jù)報后,從TCP數(shù)據(jù)報首部的同步比特SYN位為1就知道這是一個建立連接的請求。服務(wù)器如果同意,會發(fā)回確認。在確認報文段中把同步比特位SYN設(shè)置為1,確認比特位ACK設(shè)置為1,由于TCP請求報文段中的序號是x,所以服務(wù)器在發(fā)送確認報文段中的確認號ack是x+1,同時把確認報文段中的序號seq設(shè)置為y,表明服務(wù)器發(fā)送數(shù)據(jù)的初始序列號為y。該報文段也不能攜帶數(shù)據(jù)(因為SYN=1,所以不攜帶任何數(shù)據(jù))
第三次握手:客戶端收到服務(wù)器端的報文段后,要對服務(wù)器端中的SYN進行確認。在確認報文段中把確認比特位ACK設(shè)置為1,然后把確認號ack設(shè)置為y+1,自身的序號seq設(shè)置x+1。
注:客戶的初始序列號為x,服務(wù)器的初始序列號為y,那么確認報文段中的確認號ack就是所期待的對方要發(fā)送的下一個序列號
二、四次揮手
例子:
A:“喂,我不說了 (FIN)。”A->FIN_WAIT
B:“我知道了(ACK)。等下,上一句還沒說完。Balabala…..(傳輸數(shù)據(jù))”B->CLOSE_WAIT | A->FIN_WAIT2
B:”好了,說完了,我也不說了(FIN)。”B->LAST_ACK
A:”我知道了(ACK)。”A->TIME_WAIT | B->CLOSED
圖文說明:

第一次揮手:假設(shè)客戶端執(zhí)行主動關(guān)閉,那么它會向服務(wù)器端發(fā)出釋放連接的報文段,這個TCP報文段中終止比特FIN置為1,序號seq設(shè)置為u(假設(shè)上一個發(fā)的數(shù)據(jù)序號是u-1)。并停止發(fā)送數(shù)據(jù)。主動關(guān)閉TCP連接。等待服務(wù)器的確認,這里需要注意,因為TCP是全雙工的,所以TCP連接上有兩條數(shù)據(jù)通路,發(fā)送FIN的一端就不能發(fā)送數(shù)據(jù),也就是關(guān)閉了其中一條數(shù)據(jù)通路,對方還是可以繼續(xù)發(fā)送數(shù)據(jù)。
第二次揮手:服務(wù)器端收到客戶端的釋放連接的報文段后會執(zhí)行被動關(guān)閉,它要對客戶端的數(shù)據(jù)報進行確認,服務(wù)器端會發(fā)送一個確認的數(shù)據(jù)報,確認比特ACK設(shè)置為1,確認號為u+1,自身的序號seq為v(假設(shè)上一個發(fā)的數(shù)據(jù)序號是v-1)。這個時候TCP處于半關(guān)閉狀態(tài),服務(wù)器依然可以向客戶端發(fā)送數(shù)據(jù)(數(shù)據(jù)的序號為v+1 ~ w-1),客戶端任要接受。
第三次揮手:服務(wù)器端已經(jīng)沒有要發(fā)送給客戶端的數(shù)據(jù),那么服務(wù)器端也會調(diào)用close關(guān)閉套接字,這樣服務(wù)器端也會發(fā)送一個FIN的TCP報文段,序號是w(假設(shè)上一個發(fā)的數(shù)據(jù)序號是w-1)。這個時候服務(wù)器端不會再向客戶端發(fā)送數(shù)據(jù)了。
第四次揮手:客戶端接受到這個最終的FIN的釋放連接報文段后必須對報文段進行確認。在確認的報文段中,ACK=1,確認序號ack=w+1,自己的序號seq=u+1(他的上一個序號的數(shù)據(jù)報就是申請釋放連接的數(shù)據(jù)報,序號是seq=u)。
三、TCP連接11種狀態(tài)
客戶端獨有的狀態(tài):SYN_SENT 、FIN_WAIT1 、FIN_WAIT2 、CLOSING 、TIME_WAIT 。
服務(wù)器獨有的狀態(tài):LISTEN 、SYN_RCVD 、CLOSE_WAIT 、LAST_ACK 。
共有的狀態(tài):CLOSED 、ESTABLISHED 。
l SYN_SENT :這個狀態(tài)與SYN_RCVD 狀態(tài)相呼應(yīng),當客戶端SOCKET執(zhí)行connect()進行連接時,它首先發(fā)送SYN報文,然后隨即進入到SYN_SENT 狀態(tài),并等待服務(wù)端的發(fā)送三次握手中的第2個報文。SYN_SENT 狀態(tài)表示客戶端已發(fā)送SYN報文。
2 FIN_WAIT_1 :這個狀態(tài)得好好解釋一下,其實FIN_WAIT_1 和FIN_WAIT_2 兩種狀態(tài)的真正含義都是表示等待對方的FIN報文。而這兩種狀態(tài)的區(qū)別是:FIN_WAIT_1狀態(tài)實際上是當SOCKET在ESTABLISHED狀態(tài)時,它想主動關(guān)閉連接,向?qū)Ψ桨l(fā)送了FIN報文,此時該SOCKET進入到FIN_WAIT_1 狀態(tài)。而當對方回應(yīng)ACK報文后,則進入到FIN_WAIT_2 狀態(tài)。當然在實際的正常情況下,無論對方處于任何種情況下,都應(yīng)該馬上回應(yīng)ACK報文,所以FIN_WAIT_1 狀態(tài)一般是比較難見到的,而FIN_WAIT_2 狀態(tài)有時仍可以用netstat看到。
3 FIN_WAIT_2 :上面已經(jīng)解釋了這種狀態(tài)的由來,實際上FIN_WAIT_2狀態(tài)下的SOCKET表示半連接,即有一方調(diào)用close()主動要求關(guān)閉連接。注意:FIN_WAIT_2 是沒有超時的(不像TIME_WAIT 狀態(tài)),這種狀態(tài)下如果對方不關(guān)閉(不配合完成4次揮手過程),那這個 FIN_WAIT_2 狀態(tài)將一直保持到系統(tǒng)重啟,越來越多的FIN_WAIT_2 狀態(tài)會導致內(nèi)核crash。
4 CLOSING :這種狀態(tài)在實際情況中應(yīng)該很少見,屬于一種比較罕見的例外狀態(tài)。正常情況下,當一方發(fā)送FIN報文后,按理來說是應(yīng)該先收到(或同時收到)對方的ACK報文,再收到對方的FIN報文。但是CLOSING 狀態(tài)表示一方發(fā)送FIN報文后,并沒有收到對方的ACK報文,反而卻也收到了對方的FIN報文。什么情況下會出現(xiàn)此種情況呢?那就是當雙方幾乎在同時close()一個SOCKET的話,就出現(xiàn)了雙方同時發(fā)送FIN報文的情況,這是就會出現(xiàn)CLOSING 狀態(tài),表示雙方都正在關(guān)閉SOCKET連接。
5 TIME_WAIT :表示收到了對方的FIN報文,并發(fā)送出了ACK報文。 TIME_WAIT狀態(tài)下的TCP連接會等待2*MSL(Max Segment Lifetime,最大分段生存期,指一個TCP報文在Internet上的最長生存時間。每個具體的TCP協(xié)議實現(xiàn)都必須選擇一個確定的MSL值,RFC 1122建議是2分鐘,但BSD傳統(tǒng)實現(xiàn)采用了30秒,Linux可以cat /proc/sys/net/ipv4/tcp_fin_timeout看到本機的這個值),然后即可回到CLOSED 可用狀態(tài)了。如果FIN_WAIT_1狀態(tài)下,收到了對方同時帶FIN標志和ACK標志的報文時,可以直接進入到TIME_WAIT狀態(tài),而無須經(jīng)過FIN_WAIT_2狀態(tài)。(這種情況應(yīng)該就是四次揮手變成三次揮手的那種情況)
6 LISTEN :表示服務(wù)器端的某個SOCKET處于監(jiān)聽狀態(tài),可以接受客戶端的連接。
7 SYN_RCVD :表示服務(wù)器接收到了來自客戶端請求連接的SYN報文。在正常情況下,這個狀態(tài)是服務(wù)器端的SOCKET在建立TCP連接時的三次握手會話過程中的一個中間狀態(tài),很短暫,基本上用netstat很難看到這種狀態(tài),除非故意寫一個監(jiān)測程序,將三次TCP握手過程中最后一個ACK報文不予發(fā)送。當TCP連接處于此狀態(tài)時,再收到客戶端的ACK報文,它就會進入到ESTABLISHED 狀態(tài)。
8 CLOSE_WAIT :表示正在等待關(guān)閉。怎么理解呢?當對方close()一個SOCKET后發(fā)送FIN報文給自己,你的系統(tǒng)毫無疑問地將會回應(yīng)一個ACK報文給對方,此時TCP連接則進入到CLOSE_WAIT狀態(tài)。接下來呢,你需要檢查自己是否還有數(shù)據(jù)要發(fā)送給對方,如果沒有的話,那你也就可以close()這個SOCKET并發(fā)送FIN報文給對方,即關(guān)閉自己到對方這個方向的連接。有數(shù)據(jù)的話則看程序的策略,繼續(xù)發(fā)送或丟棄。簡單地說,當你處于CLOSE_WAIT 狀態(tài)下,需要完成的事情是等待你去關(guān)閉連接。
9 LAST_ACK :當被動關(guān)閉的一方在發(fā)送FIN報文后,等待對方的ACK報文的時候,就處于LAST_ACK 狀態(tài)。當收到對方的ACK報文后,也就可以進入到CLOSED 可用狀態(tài)了
10 CLOSED:初始狀態(tài),表示TCP連接是“關(guān)閉著的”或“未打開的”。
11 ESTABLISHED :表示TCP連接已經(jīng)成功建立。

浙公網(wǎng)安備 33010602011771號