TCP三次握手:
圖3
第一次握手:建立連接。客戶端發送位碼為SYN=1,隨機產生一個值seq=x(隨機產生的一個序號)的數據包發送到服務器,要求建立連接,然后客戶端進入SYN_SENT(同步已發送)狀態,等待服務器的確認。
第二次握手:服務器收到請求要確認連接信息,發送SYN=1,ACK=1,ack=x+1(確認號,意思就是你發的x包我收到了,希望下次你發x+1的包),seq=y(隨機產生),的數據包發送給客戶端確認連接請求,服務器進入SYN_RCVD(同步收到)狀態。(ACK表示標記位,ack表示確認號)
第三次握手:客戶端收到后發送ACK=1(確認收到了服務器發的請求),seq=x+1(上次發送的是x包,這次發送x+1的包),ack=y+1(確認收到y給服務器,客戶端和服務器都進入ESTABLISHED(已建立連接)狀態,完成三次握手。
(之所以會是三次握手,是出于安全考慮。雖然三次握手也有隱患,相對來說較合適)
TCP四次揮手:(以客戶端揮手為例)
圖2
第一次揮手:客戶端發送FIN=1(發送關閉連接請求),seq=u去關閉客戶端到服務器的數據傳送,客戶端進入FIN_WAIT_1(終止等待1)狀態。
第二次揮手:服務器收到FIN后,發送ACK=1(關閉連接請求收到了)給客戶機,seq=v(隨機生成的號),ack=u+1(確認客戶端發送的u收到了,希望下次發u+1),服務器進入CLOSE_WAIT(關閉等待)狀態。
第三次揮手:服務器發送FIN=1,ACK=1,seq=w,ack=u+1(確認收到了u+1)用來關閉服務器到客戶端的數據傳送,服務器進入LAST_ACK(最后確認)狀態。
第四次揮手:客戶端收到FIN后,進入TIME_WAIT(時間等待)狀態,接著發送ACK=1,seq=u+1(確認收到u+1),ack=w+1(收到w,希望下次發w+1)給服務器,服務器進入CLOSED狀態,完成四次揮手。
狀態:
CLOSED 沒有任何連接狀態
LISTEN 偵聽狀態,等待來自遠方TCP端口的連接請求
SYN-SENT 在發送連接請求后,等待對方確認
SYN-RECEIVED 在收到和發送一個連接請求后,等待對方確認
ESTABLISHED 代表傳輸連接建立,雙方進入數據傳送狀態
FIN-WAIT-1 主動關閉,主機已發送關閉連接請求,等待對方確認
FIN-WAIT-2 主動關閉,主機已收到對方關閉傳輸連接確認,等待對方發送關閉傳輸連接請求
TIME-WAIT 完成雙向傳輸連接關閉,等待所有分組消失
CLOSE-WAIT 被動關閉,收到對方發來的關閉連接請求,并已確認
LAST-ACK 被動關閉,等待最后一個關閉傳輸連接確認,并等待所有分組消失
LOSING 雙方同時嘗試關閉傳輸連接,等待對方確認
注:
1.為什么建立連接協議是三次握手,而關閉連接卻是四次握手呢?
這是因為服務端的LISTEN狀態下的SOCKET當收到SYN報文的建連請求后,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文里來發送。但關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你所有的數據都全部發送給對方了,所以你可以未必會馬上會關閉SOCKET,也即你可能還需要發送一些數據給對方之后,再發送FIN報文給對方來表示你同意現在可以關閉連接了,所以它這里的ACK報文和FIN報文多數情況下都是分開發送的。
2.為什么TIME_WAIT狀態還需要等2MSL后才能返回到CLOSED狀態?
這是因為雖然雙方都同意關閉連接了,而且握手的4個報文也都協調和發送完畢,按理可以直接回到CLOSED狀態(就好比從SYN_SEND狀態到ESTABLISH狀態那樣);但是因為我們必須要假想網絡是不可靠的,你無法保證你最后發送的ACK報文會一定被對方收到,因此對方處于LAST_ACK狀態下的SOCKET可能會因為超時未收到ACK報文,而重發FIN報文,所以這個TIME_WAIT狀態的作用就是用來重發可能丟失的ACK報文。
原創文章,作者:吼吼哈嘿,如若轉載,請注明出處:http://www.www58058.com/85993