1. 程式人生 > >TCP三次握手、四次端口和有限狀態機

TCP三次握手、四次端口和有限狀態機

TCP三次握手、四次端口和有限狀態機

1、TCP用三次握手(three-way handshake)

一對終端同時初始化一個它們之間的連接是可能的。但通常是由一端打開一個套接字(socket)然後監聽來自另一方的連接,這就是通常所指的被動打開(passive open)。服務器端被被動打開以後,用戶端就能開始創建主動打開(active open)。
(1)第一次握手:
Client將標誌位SYN置為1,隨機產生一個值seq=J,並將該數據包發送給Server,Client進入SYN_SENT狀態,等待Server確認。

(2)第二次握手:
Server收到數據包後由標誌位SYN=1知道Client請求建立連接,Server將標誌位SYN和ACK都置為1,ack=J+1,隨機產生一個值seq=K,並將該數據包發送給Client以確認連接請求,Server進入SYN_RCVD狀態。

(3)第三次握手:
Client收到確認後,檢查ack是否為J+1,ACK是否為1,如果正確則將標誌位ACK置為1,ack=K+1,並將該數據包發送給Server,Server檢查ack是否為K+1,ACK是否為1,如果正確則連接建立成功,Client和Server進入ESTABLISHED狀態,完成三次握手,隨後Client與Server之間可以開始傳輸數據了。

技術分享圖片

2、TCP四次斷開

TCP連接終止使用了四路握手過程(four-wayhandshake),在這個過程中每個終端的連接都能獨立地被終止。因此,一個典型的拆接過程需要每個終端都提供一對FIN和ACK。

對於一個已經建立的連接,TCP使用改進的三次握手來釋放連接(使用一個帶有FIN附加標記的報文段)。TCP關閉連接的步驟如下:

第一次揮手:Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態。
第二次揮手:Server收到FIN後,發送一個ACK給Client,確認序號為收到序號+1(與SYN相同,一個FIN占用一個序號),Server進入CLOSE_WAIT狀態。
第三次揮手:Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態。
第四次揮手:Client收到FIN後,Client進入TIME_WAIT狀態,接著發送一個ACK給Server,確認序號為收到序號+1,Server進入CLOSED狀態,完成四次揮手。

技術分享圖片

為什麽連接的時候是三次握手,關閉的時候卻是四次握手?
為什麽A還要發送一次確認呢?這主要是為了防止已失效的連接請求報文段突然又傳送到了B,因而產生錯誤。
  所謂已失效的連接請求報文段是這樣產生的。A發送連接請求,但因連接請求報文丟失而未收到確認,於是A重發一次連接請求,成功後建立了連接。數據傳輸完畢後就釋放了連接。現在假定A發出的第一個請求報文段並未丟失,而是在某個網絡節點長時間滯留了,以致延誤到連接釋放以後的某個時間才到達B。本來這是一個早已失效的報文段。但B收到此失效的連接請求報文段後,就誤以為A又發了一次新的連接請求,於是向A發出確認報文段,同意建立連接。假如不采用三次握手,那麽只要B發出確認,新的連接就建立了。
  由於A並未發出建立連接的請求,因此不會理睬B的確認,也不會向B發送數據。但B卻以為新的運輸連接已經建立了,並一直等待A發來數據,因此白白浪費了許多資源。
  采用TCP三次握手的方法可以防止上述現象發生。例如在剛才的情況下,由於A不會向B的確認發出確認,連接就不會建立。
如果在TCP第三次握手中的報文段丟失了會發生什麽情況?
Client認為這個連接已經建立,如果Client端向Server寫數據,Server端將以RST包響應,方能感知到Server的錯誤。
為什麽需要四次揮手
①、為了保證A發送的最後一個ACK報文段能夠到達B。即最後這個確認報文段很有可能丟失,那麽B會超時重傳,然後A再一次確認,同時啟動2MSL計時器,如此下去。如果沒有等待時間,發送完確認報文段就立即釋放連接的話,B就無法重傳了(連接已被釋放,任何數據都不能出傳了),因而也就收不到確認,就無法按照步驟進入CLOSE狀態,即必須收到確認才能close。
②、防止“已失效的連接請求報文段”出現在連接中。經過2MSL,那些在這個連接持續的時間內,產生的所有報文段就可以都從網絡中消失。即在這個連接釋放的過程中會有一些無效的報文段滯留在樓閣結點,但是呢,經過2MSL這些無效報文段就肯定可以發送到目的地,不會滯留在網絡中。這樣的話,在下一個連接中就不會出現上一個連接遺留下來的請求報文段了。

技術分享圖片

3、TCP有限狀態機

技術分享圖片
(1)CLOSED 狀態時初始狀態。
(2)LISTEN:被動打開,服務器端的 狀態變為LISTEN(監聽).
(3)SYNRECVD:服務器端收到SYN後,狀態為)SYNRECVD;發送SYN ACK;
(4)SYN_SENT:客戶端發送SYN後,狀態為SYN_SENT;
(5)ESTABLISHED:SYNRECVD收到ACK後,狀態為ESTABLISHED; SYN_SENT在收到SYN ACK,發送ACK,狀態為ESTABLISHED;
(6)CLOSE_WAIT:服務器端在收到FIN後,發送ACK,狀態為CLOSE_WAIT;如果此時服務器端還有數據需要發送,那麽就發送,直到數據發送完畢;此時,服務器端發送FIN,狀態變為LAST_ACK;
(7)FIN_WAIT_1:客戶端發送FIN,準備斷開TCP連接;狀態從ESTABLISHED——>FIN_WAIT_1;
(8)FIN_WAIT_2:應用程序端只收到服務器端得ACK信號,並沒有收到FIN信號;說明服務器端還有數據傳輸,那麽此時為半連接;
(9)TIME_WAIT:有兩種方式進入 該狀態:1、FIN_WAIT_1進入:客戶端口收到FIN+ACK(而不是像FIN_WAIT_2那樣只收到ACK,說明數據已經發送完畢)並 向服務器端口發送ACK;2、FIN_WAIT_2進入:此時應用程序端口收到了FIN,然後向服務器端發送ACK;TIME_WAIT是為了實現TCP 全雙工連接的可靠性關閉,用來重發可能丟失的ACK報文;需要持續2個MSL(最大報文生存時間):假設應用程序端口在進入TIME_WAIT後,2個 MSL時間內並沒有收到FIN,說明應用程序最後發出的ACK已經收到了;否則,會在2個MSL內在此收到ACK報文;
4.1.客戶端應用程序的狀態遷移圖
客戶端的狀態可以用如下的流程來表示:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
以上流程是在程序正常的情況下應該有的流程,從書中的圖中可以看到,在建立連接時,當客戶端收到SYN報文的ACK以後,客戶端就打開了數據交互地連接。而結束連接則通常是客戶端主動結束的,客戶端結束應用程序以後,需要經歷FIN_WAIT_1,FIN_WAIT_2等狀態,這些狀態的遷移就是前面提到的結束連接的四次握手。
4.2.服務器的狀態遷移圖
服務器的狀態可以用如下的流程來表示:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
在建立連接的時候,服務器端是在第三次握手之後才進入數據交互狀態,而關閉連接則是在關閉連接的第二次握手以後(註意不是第四次)。而關閉以後還要等待客戶端給出最後的ACK包才能進入初始的狀態。
4.3.其他狀態遷移
書中的圖還有一些其他的狀態遷移,這些狀態遷移針對服務器和客戶端兩方面的總結如下
LISTEN->SYN_SENT,對於這個解釋就很簡單了,服務器有時候也要打開連接的嘛。
SYN_SENT->SYN收到,服務器和客戶端在SYN_SENT狀態下如果收到SYN數據報,則都需要發送SYN的ACK數據報並把自己的狀態調整到SYN收到狀態,準備進入ESTABLISHED
SYN_SENT->CLOSED,在發送超時的情況下,會返回到CLOSED狀態。
SYN_收到->LISTEN,如果受到RST包,會返回到LISTEN狀態。
SYN_收到->FIN_WAIT_1,這個遷移是說,可以不用到ESTABLISHED狀態,而可以直接跳轉到FIN_WAIT_1狀態並等待關閉。
4.4.2MSL等待狀態
書中給的圖裏面,有一個TIME_WAIT等待狀態,這個狀態又叫做2MSL狀態,說的是在TIME_WAIT2發送了最後一個ACK數據報以後,要進入TIME_WAIT狀態,這個狀態是防止最後一次握手的數據報沒有傳送到對方那裏而準備的(註意這不是四次握手,這是第四次握手的保險狀態)。這個狀態在很大程度上保證了雙方都可以正常結束,但是,問題也來了。
由於插口的2MSL狀態(插口是IP和端口對的意思,socket),使得應用程序在2MSL時間內是無法再次使用同一個插口的,對於客戶程序還好一些,但是對於服務程序,例如httpd,它總是要使用同一個端口來進行服務,而在2MSL時間內,啟動httpd就會出現錯誤(插口被使用)。為了避免這個錯誤,服務器給出了一個平靜時間的概念,這是說在2MSL時間內,雖然可以重新啟動服務器,但是這個服務器還是要平靜的等待2MSL時間的過去才能進行下一次連接。
4.5.FIN_WAIT_2狀態
這就是著名的半關閉的狀態了,這是在關閉連接時,客戶端和服務器兩次握手之後的狀態。在這個狀態下,應用程序還有接受數據的能力,但是已經無法發送數據,但是也有一種可能是,客戶端一直處於FIN_WAIT_2狀態,而服務器則一直處於WAIT_CLOSE狀態,而直到應用層來決定關閉這個狀態。
5.RST,同時打開和同時關閉
RST是另一種關閉連接的方式,應用程序應該可以判斷RST包的真實性,即是否為異常中止。而同時打開和同時關閉則是兩種特殊的TCP狀態,發生的概率很小。

TCP三次握手、四次端口和有限狀態機