建立tcp連接需要三次握手,斷開連接需要4次。
三次握手:首先Client端發送連接請求報文,Server段接受連接后回復ACK報文,并為這次連接分配資源。Client端接收到ACK報文后也向Server段發生ACK報文,并分配資源,這樣TCP連接就建立了。
為什么需要三次握手?
謝希仁版《計算機網絡》中的例子是這樣的,“已失效的連接請求報文段”的產生在這樣一種情況下:client發出的第一個連接請求報文段并沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以后的某個時間才到達server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段后,就誤認為是client再次發出的一個新的連接請求。于是就向client發出確認報文段,同意建立連接。假設不采用“三次握手”,那么只要server發出確認,新的連接就建立了。由于現在client并沒有發出建立連接的請求,因此不會理睬server的確認,也不會向server發送ack包。server卻以為新的運輸連接已經建立,并一直等待client發來數據。這樣,server的很多資源就白白浪費掉了。采用“三次握手”的辦法可以防止上述現象發生。例如剛才那種情況,client不會向server的確認發出確認。server由于收不到確認,就知道client并沒有要求建立連接。在謝希仁著《計算機網絡》第四版中講“三次握手”的目的是“為了防止已失效的連接請求報文段突然又傳送到了服務端,因而產生錯誤”。在另一部經典的《計算機網絡》一書中講“三次握手”的目的是為了解決“網絡中存在延遲的重復分組”的問題。這兩種不同的表述其實闡明的是同一個問題。
那如何斷開連接呢?簡單的過程如下
1.假設客戶端主動斷開連接,向服務器發送fin報文,這個報文主要告訴服務器客戶端已經沒有數據想要傳給服務器,但是服務器你如果有數據沒傳輸完的話,先不用斷開socket連接,可以繼續發你的數據,先給客戶端發ack報文。2.服務器收到報文,看了fin的報文,給客戶端發了ack報文,告訴客戶端服務器已經收到了消息,但我還有事沒做完,讓客戶端等會。3.這時候客戶端進入FIN_WAIT狀態,即等待服務器給他發fin報文。當服務器確定傳輸的數據都發完了,再向客戶端發送fin報文。告訴客戶端我已經傳輸完所有數據了,可以關閉socket連接。4.客戶端收到fin報文,就知道socket要斷開連接了,向服務器發送ack報文,但客戶端不確定這個報文是否傳到服務器了,于是進入Time_wait狀態,如果服務器沒有收到ack報文則進行重傳,如果等待30s沒有收到消息說明連接服務器端已經關閉了,客戶端可以安心關閉了。這樣tcp就斷開了。
【注意】在TIME_WAIT狀態中,如果TCP client端最后一次發送的ACK丟失了,它將重新發送。TIME_WAIT狀態中所需要的時間是依賴于實現方法的。典型的值為30秒、1分鐘和2分鐘。等待之后連接正式關閉,并且所有的資源(包括端口號)都被釋放。
為什么連接的時候是三次握手,關閉的時候卻是四次握手?
答:因為當Server端收到Client端的SYN連接請求報文后,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連接時,當Server端收到FIN報文時,很可能并不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送。故需要四步握手。