天天看點

Tcp建立三次握手和關閉四次握手

本文大部分來自:

 http://blog.csdn.net/whuslei/article/details/6667471

一、基本概念:

   說來慚愧,工作這麼久一直對TCP的三次握手模模糊糊,最近排查jedis connection time out過多的問題,才發現了解TCP協定非常的重要。

     上一張圖簡單說明一下:

    (1)建立連接配接: TCP協定建立連接配接需要三次握手

    (2)發送資料:...

    (3)釋放連接配接:TCP協定釋放連接配接需要四次握手

     ps: 何為長連接配接?比如Socket可以實作TCP連接配接,如果開啟了長連配置,會長時間持有連接配接,減少了不必要的連接配接開銷。

Tcp建立三次握手和關閉四次握手

二、 建立連接配接的三次握手:

1. 這個例子看着很容易了解:用戶端發送序号1-1000,服務端回了個1001,說明服務端收到1-1000才知道下一個是1001

Tcp建立三次握手和關閉四次握手

2. 如果抽象的說就是下面這張圖。ack代表應答(因為第一次沒有應答是以是0,seq是序号相當于上面的1-1000)

    說明:

ACK : TCP協定規定,隻有ACK=1時有效,也規定連接配接建立後所有發送的封包的ACK必須為1

SYN(SYNchronization) : 在連接配接建立時用來同步序号。當SYN=1而ACK=0時,表明這是一個連接配接請求封包。對方若同意建立連接配接,則應在響應封包中使SYN=1和ACK=1. 是以, SYN置1就表示這是一個連接配接請求或連接配接接受封包。

FIN (finis)即完,終結的意思, 用來釋放一個連接配接。當 FIN = 1 時,表明此封包段的發送方的資料已經發送完畢,并要求釋放連接配接。

用戶端<-->服務端

(1) ack=0,seq=x(應答為0,序号是x)

(2) ack=x+1(說明收到序号x),seq=y(發送一個新的序号給用戶端)

(3) ack=y+1(應答是y+1), seq=x+1(新的序号)

Tcp建立三次握手和關閉四次握手

3. 和上面的圖意思是一樣的,不過第二步好像畫錯了,應該是seq=server_isn。

Tcp建立三次握手和關閉四次握手

實際過程是:首先Client端發送連接配接請求封包,Server段接受連接配接後回複ACK封包,并為這次連接配接配置設定資源。Client端接收到ACK封包後也向Server段發生ACK封包,并配置設定資源,這樣TCP連接配接就建立了。

三、斷開連接配接的四次握手:

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端所經曆的狀态如下:

Tcp建立三次握手和關閉四次握手

而Server端所經曆的過程如下:轉載請注明:

blog.csdn.net/whuslei
Tcp建立三次握手和關閉四次握手

【注意】 在TIME_WAIT狀态中,如果TCP client端最後一次發送的ACK丢失了,它将重新發送。TIME_WAIT狀态中所需要的時間是依賴于實作方法的。典型的值為30秒、1分鐘和2分鐘。等待之後連接配接正式關閉,并且所有的資源(包括端口号)都被釋放。

【問題1】為什麼連接配接的時候是三次握手,關閉的時候卻是四次握手?

答:因為當Server端收到Client端的SYN連接配接請求封包後,可以直接發送SYN+ACK封包。其中ACK封包是用來應答的,SYN封包是用來同步的。但是關閉連接配接時,當Server端收到FIN封包時,很可能并不會立即關閉SOCKET,是以隻能先回複一個ACK封包,告訴Client端,"你發的FIN封包我收到了"。隻有等到我Server端所有的封包都發送完了,我才能發送FIN封包,是以不能一起發送。故需要四步握手。

【問題2】為什麼TIME_WAIT狀态需要經過2MSL(最大封包段生存時間)才能傳回到CLOSE狀态?

答:雖然按道理,四個封包都發送完畢,我們可以直接進入CLOSE狀态了,但是我們必須假象網絡是不可靠的,有可以最後一個ACK丢失。是以TIME_WAIT狀态就是用來重發可能丢失的ACK封包。

【問題3】. 為什麼不是兩次握手:

答:那樣的話,服務端很難确定用戶端是否收到他的請求。

繼續閱讀