TCP-三次握手和四次揮手簡單理解
背景:TCP,即傳輸控制協議,是一種面向連接的可靠的,基於字節流的傳輸層協議。作用是在不可靠的互聯網絡上提供一個可靠的端到端的字節流服務,為了准確無誤的將數據送達目的地,TCP協議采納三次握手策略。
一、TCP報文
TCP報文格式圖:
上圖中的幾個字段需要重點介紹下:
字段 | 介紹 |
---|---|
序列號seq | 占4個字節,用來標記數據段的順序,TCP把連接中發送的所有數據字節都編上一個序列號,第一個序列號由本地隨機產生;給字節編上序號后,就給每一個報文指派一個序號;序列號seq就是這個報文段中的第一個字節的數據編號。 |
確認號ack | 占4個字節,期待收到對方下一個報文段段的一個數據字節的序號;序列號表示報文段攜帶數據段第一個字節的編號;而確認號指的是期望接受到下一個字節的編號;因此當前報文段最后一個字節的編號+1即為確認號。 |
確認ACK | 占1位,僅當ACK=1時,確認號字段才有效。ACK=0時,確認號無效。 |
同步SYN | 連接建立時用於同步序號。當SYN=1,ACK=0時表示:這是一個連接請求報文段。若同意連接,則在響應報文段中使得SYN=1,ACK=1。因此,SYN=1表示這是一個連接請求,或連接接受報文。SYN這個標准位只有在TCP建成連接時才會被置1,握手完成后SYN標志位被置0。 |
終止FIN | 用來釋放一個連接。FIN=1表示:此報文段段發送方的數據已經發送完畢,並要求釋放運輸連接。 |
PS:ACK、SYN和FIN這些大寫的單詞表示標志位,其值要么是1,要么是0;ack、seq小寫的單詞表示序號。
標志位:
字段 | 含義 |
---|---|
URG | 緊急指針是否有效。為1時,表示某一位需要被優先處理。 |
ACK | 確認號是否有效,一般置為1。 |
PSH | 接收方應該盡快將這個報文交給應用層。 |
RST | 重置連接。 |
SYN | 發起一個新連接。 |
FIN | 釋放一個連接。 |
注意:不要將確認序號ack與標志位中的ACK搞混了。
二、三次握手(Three-Way Handshake)
原理:
第一次握手:建立連接是,客戶端發送syn包(syn=x)到服務器,並進入SYN_SENT狀態,等待服務器確認;SYN:同步序列號。
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=x+1),同時自己也發送一個SYN包(syn=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態。
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED(TCP連接成功)狀態,完成三次握手。
為什么要三次握手?
三次握手的最主要目的是「雙方確認自己與對方的發送與接收是正常的」。
第一次握手:Client什么都不能確認;Server確認了對方發送正常。
第二次握手:Client確認了:自己發送、接收正常,對方發送、接收正常;Server確認了:自己接受正常,對方發送正常。
第三次握手:Client確認了:自己發送、接受正常,對方發送,接受正常;Server確認了:自己發送了、接受正常,對方發送、接受正常。
所以三次握手就能確認雙方收發功能是否正常。
通俗的說法:
Client:喂!聽的到嗎?
Server:可以,我聽的到。
Client:好的,我們都能互相聽的對方的話,可以開始通信了。
三次握手為什么不用兩次,或者四次?
因為只有三次才最合適,三次通信是最小值,兩次通信無法確認雙方收發功能的正常,而四次通信則顯得有些冗余。
三、四次揮手(Four-Way Wavehand)
意義:
所謂四次揮手,即終止TCP連接,就是指斷開一個TCP連接時,需要客戶端和服務的總共發送4個包以確認連接到斷開。在socket編程中,這一過程由客戶端或服務的任意一方執行close來觸發,流程如下圖所示:
由於TCP連接時是全雙工的,因此,每個方向都必須要單獨進行關閉,這一原則是主動方完成數據發送任務后,發送一個FIN來終止主動方發送數據的連接,收到一個FIN只是意味着這一方向上沒有數據流動來,即不會再收到主動方的數據,但是在這個TCP連接上被動方仍然能夠發送數據,直到被動方也發送了FIN。首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉。
原理:
第一次揮手:Client發送一個FIN,用來關閉CIient到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狀態,完成四次揮手。
通俗的說法:
Client:我已經說完了。
Server:我收到了,等等我,我還沒說完。
Server:好了,我也說完了。
Client:好的,那我們通信結束。
上面是一方主動關閉,另一方被動關閉的情況,實際中還會出現同時發起關閉的情況,如下圖所示:
為什么建立連接是三次握手,而關閉連接卻是四次揮手呢?
這是因為服務端在LISTEN狀態下,收到建立連接請求的SYN報文后,把ACK和SYN放在一個報文里發送給客戶端。而關閉連接是,當收到對方的FIN報文是,僅僅表示對方不再發送數據了,但是還能接收數據,已方也未必全部數據都發送給對方了,所以已方可以立即close,也可以發送一些數據給對方后,再發送FIN報文給對方來表示同意現在關閉連接,因此,已方ACK和FIN一般都會分開發送。