一、TCP四次揮手
MSL是TCP報文里面最大生存時間,它是任何報文段被丟棄前在網絡內的最長時間。
第一次揮手:A->B,A向B發出釋放連接請求的報文,其中FIN(終止位) = 1,seq(序列號)=u;在A發送完之后,A的TCP客戶端進入FIN-WAIT-1(終止等待1)狀態。此時A還是可以進行收數據的
第二次揮手:B->A:B在收到A的連接釋放請求后,隨即向A發送確認報文。其中ACK=1,seq=v,ack(確認號) = u +1;在B發送完畢后,B的服務器端進入CLOSE_WAIT(關閉等待)狀態。此時A收到這個確認后就進入FIN-WAIT-2(終止等待2)狀態,等待B發出連接釋放的請求。此時B還是可以發數據的。
(如果 B 直接跑路,則 A 永遠處與這個狀態。TCP 協議里面並沒有對這個狀態的處理,但 Linux 有,可以調整 tcp_fin_timeout 這個參數,設置一個超時時間。)
第三次揮手:B->A:當B已經沒有要發送的數據時,B就會給A發送一個釋放連接報文,其中FIN=1,ACK=1,seq=w,ack=u+1,在B發送完之后,B進入LAST-ACK(最后確認)狀態。
第四次揮手:A->B;當A收到B的釋放連接請求時,必須對此發出確認,其中ACK=1,seq=u+1,ack=w+1;A在發送完畢后,進入到TIME-WAIT (時間等待)狀態。B在收到A的確認之后,進入到CLOSED(關閉)狀態。在經過時間等待計時器設置的時間之后,A才會進入CLOSED狀態。
二、為什么需要四次揮手
其實是客戶端和服務端的兩次揮手,也就是客戶端和服務端分別釋放連接的過程。可以看到,客戶端在發送完最后一次確認之后,還要等待2MSL的時間。主要有兩個原因,一個是為了讓B能夠按照正常步驟進入CLOSED狀態,二是為了防止已經失效的請求連接報文出現在下次連接中。
解釋:
1)、由於客戶端最后一個ACK可能會丟失,這樣B就無法正常進入CLOSED狀態。於是B會重傳請求釋放的報文,而此時A如果已經關閉了,那就收不到B的重傳請求,就會導致B不能正常釋放。而如果A還在等待時間內,就會收到B的重傳,然后進行應答,這樣B就可以進入CLOSED狀態了。
2)、在這2MSL等待時間里面,本次連接的所有的報文都已經從網絡中消失,從而不會出現在下次連接中。
三、有三次揮手的情況么?該情況是在協議中實現的么?
如果是三次揮手,會怎么樣?三次的話,被動關閉端在收到FIN消息之后,需要同時回復ACK和Server端的FIN消息。如果Server端在該連接上面並沒有Pending的消息要處理,那么是可以的,如果Server端還需要等待一段時間才可以關閉另外一個方向的連接,那么這樣的三次揮手就不能滿足條件。