每次面試的時候都會多多少少聊一點TCP/IP協議,那麼你是如何理解其中的三次握手四次揮手的?
首先咱們須要知道TCP是一種面向鏈接的單播協議。面試
單播協議通常指單播路由協議,單播路由協議是經過路由器將到網際網絡上某一位置的通訊從源主機轉發到目標主機。網際網絡至少有兩個經過路由器鏈接的網絡。路由器是網絡層中介系統,用於根據公用網絡層協議(如 TCP/IP)將多個網絡鏈接在一塊兒。網絡是經過路由器鏈接,並與稱爲網絡地址或網絡 ID 的同一網絡層地址相關聯的聯網基礎結構(包括中繼器、集線器和橋/ 2 層交換機)的一部分。
TCP能夠當作是一種字節流,他會處理IP層或如下層的丟包、重複以及錯誤問題。在鏈接的創建過程當中,雙方須要交換一些鏈接的的參數,這些參數能夠放在TCP頭部服務器
因此TCP提供了一種可靠、面向鏈接、字節流、傳輸層的服務,採用三次握手創建一個鏈接。採用4次揮手來關閉一個鏈接。網絡
三次握手你能夠想象成這樣的一個場景,有兩個兩我的A和B,A想給B一些包裹,B想收一些包裹,可是A懼怕給B剛發了包裹,B就走了,包裹到了之後沒有收,而B則懼怕A只是口頭上說要把包裹寄過來,B在這裏等了半天發現本身被耍了。因此這兩我的須要達成一個規定或者說是一個協議來保證雙方都能達到目的。這就須要三次握手。3d
三次握手:A對B說我要給你發一些包裹!B問A說你真的要給我發包裹嗎!而後A回答我真的真的要給你發包裹(B就像言情劇的女主同樣,A說的第一遍B是不信的,非要A再說一遍B纔信)至此A和B的協議達成,A就能夠給B發包裹啦.code
這是一種比喻,真正的表現爲:cdn
(1)第一次握手:blog
客戶端發送syn包(syn=x)到服務器,並進入SYN_SEND狀態,等待服務器確認。路由
(2)第二次握手:it
服務器收到syn包,必須確認客戶的SYN(ack=x+1),同時本身也發送一個SYN包(syn=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態。io
(3)第三次握手:
客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,萬次三次握手。
注意:以上動做發送的包中沒有任何數據,等三次握手完成後客戶端與服務器才正式開始傳送數據。而且理想狀態下,TCP鏈接一旦創建,在通訊雙方中的任何一方主動關閉鏈接以前,TCP鏈接都將被一直保持下去。
爲何要三次握手,我握兩次不行嗎?我以爲我說發,你說好,不就完了嗎,非要矯情一下,握第三次手的意義是什麼?
首先咱們先來理解一下爲何須要握手?
客戶端和服務器端通訊前須要鏈接,而」握手「做用就是爲了證實,客戶端的發送能力和服務器端的接受能力都是正常的,這是」握手「來達到的目的。
第一次握手
:客戶端發送網絡包,服務器端收到了,這樣服務器端就能證實:客戶端的發送能力、以及服務器端的接收能力都是正常的。
第二次握手:
服務端發包,客戶端收到了。這樣客戶端就能得出結論:服務端的接收、發送能力,客戶端的接收、發送能力是正常的。 從客戶端的視角來看,我接到了服務端發送過來的響應數據包,說明服務端接收到了我在第一次握手時發送的網絡包,而且成功發送了響應數據包,這就說明,服務端的接收、發送能力正常。而另外一方面,我收到了服務端的響應數據包,說明我第一次發送的網絡包成功到達服務端,這樣,我本身的發送和接收能力也是正常的。
第三次握手:
客戶端發包,服務端收到了。這樣服務端就能得出結論:客戶端的接收、發送能力,服務端的發送、接收能力是正常的。 第1、二次握手後,服務端並不知道客戶端的接收能力以及本身的發送能力是否正常。而在第三次握手時,服務端收到了客戶端對第二次握手做的迴應。從服務端的角度,我在第二次握手時的響應數據發送出去了,客戶端接收到了。因此,個人發送能力是正常的。而客戶端的接收能力也是正常的。
而從上面的過程能夠看到,最少是須要三次握手過程的。兩次達不到讓雙方都得出本身、對方的接收、發送能力都正常的結論。
TCP鏈接時雙向傳輸的對等的模式,就是說雙方都考驗同時向對方發送或者接收數據。當有一方要關閉鏈接時,會發送指令告知對方,我要關閉鏈接了。這時對方會回一個ACK,此時一個方向的鏈接關閉。可是另外一個方向仍然能夠繼續傳輸數據,等到發送完了全部數據後,會發送一個FIN段來關閉此方向上的鏈接。接收方發送ACK確認關閉鏈接。
通俗的來講就是
四次揮手: A對B說:我要和你斷開鏈接!B說:好的,斷吧! B也對A說我也要和你斷開鏈接!
A說:好的,斷吧!
真實的過程是
(1)第一次揮手
客戶端主動關閉方發送一個FIN,用來關閉客戶端到服務器端的數據傳送,也就是客戶端告訴服務器端:我已經不會再給你發數據了, (固然,在 fin 包以前發送出去的數據,若是沒有收到對應的 ack 確認報文,客戶端依然會重發這些數據),可是,此時客戶端還能夠接受數據。
(2)第二次揮手
服務端收到FIN包後,發送一個ACK給客戶端,確認序號爲收到序號+1(與 SYN 相同,一個 FIN 佔用一個序號)。
(3)第三次揮手
服務器端發送一個FIN,用來關閉服務器端到客戶端的數據傳送,也就是告訴客戶端,個人數據也發送完了,不會再給你發送數據了!!!
(4)第四次揮手
客戶端收到 FIN 後,發送一個 ACK 給服務端,確認序號爲收到序號 + 1,至此,完成四次揮手。
這是由於服務端在LISTEN(監聽)狀態下,收到創建鏈接請求的SYN報文後,把ACK和SYN放在一個報文裏發送給客戶端。而關閉鏈接時,當收到對方的FIN報文時,僅僅表示對方再也不發送數據了可是還能接收數據,己方是否如今關閉發送數據通道,須要上層應用來決定,所以,己方ACK和FIN通常都會分開發送。