1. 程式人生 > >TCP連線建立只需要三次握手,為什麼斷開連線需要四次揮手?

TCP連線建立只需要三次握手,為什麼斷開連線需要四次揮手?

通常TCP連線是由客戶端向伺服器發起和斷開的。因為只有伺服器在監聽埠,客戶端上沒有監聽埠,所以客戶端無法接收主動來的連線。而客戶端獲得了自己想要的資源或者服務之後,就會斷開連線。下面的三次握手和四次揮手描述了典型情況。

TCP連線建立過程:
1、客戶端向伺服器傳送SYN,其中seq=x。
2、伺服器收到SYN報文段後,傳送SYN+ACK,其中seq=y,確認號=x+1。
3、客戶端收到SYN+ACK報文段後,傳送ACK,確認號=y+1。伺服器收到ACK報文段後,連線建立。

建立後客戶端和伺服器就知道了對方的序列號,序列號用來做確認重傳、排序。也知道了對方的視窗大小,可以用於端到端的流控,永遠不會發送對方處理不了的資料量。
還可以通過連線過程來進行選項的協商。通過MSS(Maximum Segment Size/最大報文段長度),用於告訴對端本端能夠接收的最大Segment Size。可以協商使用選擇性的確認,而不單純是累計確認,這樣可以提高效能。還可以協商使用Window Scale Option(視窗擴大因子),將TCP視窗大小變大,用於突破65535的限制,提高長肥管道中的傳輸速率。

TCP連線斷開過程:
1、客戶端TCP模組在收到應用程式的通知後,傳送FIN,seq=x。
2、伺服器收到FIN報文段,傳送ACK,確認號=x+1,並且通知應用程式客戶端關閉了連線。客戶端收到ACK報文段。
3、伺服器端的應用程式通知TCP關閉連線,伺服器端TCP傳送FIN+ACK,seq=y,確認號=x+1(這裡ACK只是一般性的捎帶ACK,TCP總是這樣,以增強健壯性,反正也不費力氣,從原理上說,對連線斷開不是必須的)。
4、客戶端收到FIN+ACK報文段後,傳送ACK,確認號y+1。伺服器收到ACK報文段後,連線斷開。

為什麼不去掉第二步,直接進行第三步呢?
因為,第二步中,伺服器端通知應用程式並獲得反饋資訊可能需要可觀的時間,這可能涉及人機互動操作,也可能伺服器應用層暫時還不想關閉連線。第二步結束後,伺服器還可以繼續通過這條連線傳送資料給客戶端,客戶端已經不能傳送資料了,但是仍然可以回覆ACK。第二步中伺服器立即傳送確認是為了防止客戶端重傳FIN報文。

當然也有可能雙方同時來連線,這個時候通訊雙方是對等的,比如BGP peer之間就是對等的,翻譯成中文為BGP對等體,也算是貼切。如果雙發使用非監聽埠發起連線,這樣最終需要斷開其中一條多餘的連線。如果雙發都使用自己監聽的埠發起連線,那就成了四次握手,正好建立起一條雙向連線。

也有可能伺服器在不想繼續為客戶端提供服務了,主動斷開連線。不過這種情況對於TCP而言仍然是普通的四次揮手。

還有可能客戶端和伺服器同時斷開連線,仍然是傳送四個報文,你可以把它看做是四次揮手,但是它不再是普通的四次揮手。因為這4個報文在時間上有重疊。就TCP狀態機的遷移而言,也和普通的四次揮手不同。將不再進入FIN-WAIT-2狀態。