1. 程式人生 > >通俗大白話來理解TCP協議的三次握手和四次分手

通俗大白話來理解TCP協議的三次握手和四次分手

network層 三次 udp 三層 等了 吃飯 號碼 adc ip首部

通俗理解:

技術分享圖片

但是為什麽一定要進行三次握手來保證連接是雙工的呢,一次不行麽?兩次不行麽?我們舉一個現實生活中兩個人進行語言溝通的例子來模擬三次握手。

引用網上的一些通俗易懂的例子,雖然不太正確,後面會指出,但是不妨礙我們理解,大體就是這麽個理解法。

第一次對話:

老婆讓甲出去打醬油,半路碰到一個朋友乙,甲問了一句:哥們你吃飯了麽?

結果乙帶著耳機聽歌呢,根本沒聽到,沒反應。甲心裏想:跟你說話也沒個音,不跟你說了,溝通失敗。說明乙接受不到甲傳過來的信息的情況下溝通肯定是失敗的。

如果乙聽到了甲說的話,那麽第一次對話成功,接下來進行第二次對話。

第二次對話:

乙聽到了甲說的話,但是他是老外,中文不好,不知道甲說的啥意思也不知道怎樣回答,於是隨便回答了一句學過的中文 :我去廁所了。甲一聽立刻笑噴了,“去廁所吃飯”?道不同不相為謀,離你遠點吧,溝通失敗。說明乙無法做出正確應答的情況下溝通失敗。

如果乙聽到了甲的話,做出了正確的應答,並且還進行了反問:我吃飯了,你呢?那麽第二次握手成功。

通過前兩次對話證明了乙能夠聽懂甲說的話,並且能做出正確的應答。 接下來進行第三次對話。

第三次對話:

甲剛和乙打了個招呼,突然老婆喊他,“你個死鬼,打個醬油咋這麽半天,看我回家咋收拾你”,甲是個妻管嚴,聽完嚇得二話不說就跑回家了,把乙自己晾那了。乙心想:這什麽人啊,得,我也回家吧,溝通失敗。說明甲無法做出應答的情況下溝通失敗。

如果甲也做出了正確的應答:我也吃了。那麽第三次對話成功,兩人已經建立起了順暢的溝通渠道,接下來開始持續的聊天。

通過第二次和第三次的對話證明了甲能夠聽懂乙說的話,並且能做出正確的應答。

可見,兩個人進行有效的語言溝通,這三次對話的過程是必須的。

為了保證服務端能收接受到客戶端的信息並能做出正確的應答而進行前兩次(第一次和第二次)握手,為了保證客戶端能夠接收到服務端的信息並能做出正確的應答而進行後兩次(第二次和第三次)握手。

這個例子舉得挺好的。不過個人感覺為什麽是三次而不是二次,不是因為為了證明甲能聽懂乙並回應(第二次乙能正確的響應甲說明倆人之間溝通已無障礙了),而是怕出現以下情況而浪費感情。這個情景是這樣的(例子有點不實際意會就好):甲在路上跟乙打招呼,由於刮風什麽的這句活被吹跑了,然後甲又跟打了個招呼,乙聽到了並作出了回應。此時不管是三次握手還是兩次握手兩個人都能愉快的溝通。0.1秒後倆人四次揮手告別了。此時被風刮跑的那句話又傳到了乙的耳朵裏,乙認為甲又要跟他溝通,所以做出了響應的回應。(問題出現了)假如采用2次握手,乙就認定了甲要跟他溝通,於是就不停的等,浪費感情。可如果是采用3次握手,乙等了一會後發現甲沒有回應他就認為甲走了然後自己也就走了!

這就很明白了,其實第三步是防止了乙的一直等待而浪費自己的時間,而不是為了保證甲能夠正確回應乙的信息。。。後面的也會講到。

引用知乎上的別人引用的一個回答,從另外一個角度闡釋:

在Google Groups的TopLanguage中看到一帖討論TCP“三次握手”覺得很有意思。貼主提出“TCP建立連接為什麽是三次握手?”的問題,在眾多回復中,有一條回復寫道:“這個問題的本質是, 信道不可靠, 但是通信雙發需要就某個問題達成一致. 而要解決這個問題, 無論你在消息中包含什麽信息, 三次通信是理論上的最小值. 所以三次握手不是TCP本身的要求, 而是為了滿足"在不可靠信道上可靠地傳輸信息"這一需求所導致的. 請註意這裏的本質需求,信道不可靠, 數據傳輸要可靠. 三次達到了, 那後面你想接著握手也好, 發數據也好, 跟進行可靠信息傳輸的需求就沒關系了. 因此,如果信道是可靠的, 即無論什麽時候發出消息, 對方一定能收到, 或者你不關心是否要保證對方收到你的消息, 那就能像UDP那樣直接發送消息就可以了.”。這可視為對“三次握手”目的的另一種解答思路。

上面的純屬大白話娛樂講解,可能還有偏差,例子可能有點不得體。在我們真正了解TCP的三次握手和四次分手之前,必須了解一些基本的概念,最後和這大白話例子對比結合一下理解,說不定就會頓時融會貫通。

??

HTTP連接

HTTP協議即超文本傳送協議(Hypertext Transfer Protocol ),是Web聯網的基礎,也是手機聯網常用的協議之一,HTTP協議是建立在TCP協議之上的一種應用。
HTTP連接最顯著的特點是客戶端發送的每次請求都需要服務器回送響應,在請求結束後,會主動釋放連接。從建立連接到關閉連接的過程稱為“一次連接”。
1)在HTTP 1.0中,客戶端的每次請求都要求建立一次單獨的連接,在處理完本次請求後,就自動釋放連接。

2)在HTTP 1.1中則可以在一次連接中處理多個請求,並且多個請求可以重疊進行,不需要等待一個請求結束後再發送下一個請求。

由於HTTP在每次請求結束後都會主動釋放連接,因此HTTP連接是一種“短連接”,要保持客戶端程序的在線狀態,需要不斷地向服務器發起連接請求。通常 的做法是即時不需要獲得任何數據,客戶端也保持每隔一段固定的時間向服務器發送一次“保持連接”的請求,服務器在收到該請求後對客戶端進行回復,表明知道 客戶端“在線”。若服務器長時間無法收到客戶端的請求,則認為客戶端“下線”,若客戶端長時間無法收到服務器的回復,則認為網絡已經斷開。

???

SOCKET原理

套接字(socket)概念

套接字(socket)是通信的基石,是支持TCP/IP協議的網絡通信的基本操作單元。它是網絡通信過程中端點的抽象表示,包含進行網絡通信必須的五種信息:連接使用的協議,本地主機的IP地址,本地進程的協議端口,遠地主機的IP地址,遠地進程的協議端口。
應用層通過傳輸層進行數據通信時,TCP會遇到同時為多個應用程序進程提供並發服務的問題。多個TCP連接或多個應用程序進程可能需要通過同一個 TCP協議端口傳輸數據。為了區別不同的應用程序進程和連接,許多計算機操作系統為應用程序與TCP/IP協議交互提供了套接字(Socket)接口。應 用層可以和傳輸層通過Socket接口,區分來自不同應用程序進程或網絡連接的通信,實現數據傳輸的並發服務。

建立socket連接

建立Socket連接至少需要一對套接字,其中一個運行於客戶端,稱為ClientSocket ,另一個運行於服務器端,稱為ServerSocket 。
套接字之間的連接過程分為三個步驟:服務器監聽,客戶端請求,連接確認。
服務器監聽:服務器端套接字並不定位具體的客戶端套接字,而是處於等待連接的狀態,實時監控網絡狀態,等待客戶端的連接請求。
客戶端請求:指客戶端的套接字提出連接請求,要連接的目標是服務器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務器的套接字,指出服務器端套接字的地址和端口號,然後就向服務器端套接字提出連接請求。
連接確認:當服務器端套接字監聽到或者說接收到客戶端套接字的連接請求時,就響應客戶端套接字的請求,建立一個新的線程,把服務器端套接字的描述發 給客戶端,一旦客戶端確認了此描述,雙方就正式建立連接。而服務器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連接請求。

SOCKET連接與TCP連接

創建Socket連接時,可以指定使用的傳輸層協議,Socket可以支持不同的傳輸層協議(TCP或UDP),當使用TCP協議進行連接時,該Socket連接就是一個TCP連接。

Socket連接與HTTP連接

由於通常情況下Socket連接就是TCP連接,因此Socket連接一旦建立,通信雙方即可開始相互發送數據內容,直到雙方連接斷開。但在實際網 絡應用中,客戶端到服務器之間的通信往往需要穿越多個中間節點,例如路由器、網關、防火墻等,大部分防火墻默認會關閉長時間處於非活躍狀態的連接而導致 Socket 連接斷連,因此需要通過輪詢告訴網絡,該連接處於活躍狀態。
而HTTP連接使用的是“請求—響應”的方式,不僅在請求時需要先建立連接,而且需要客戶端向服務器發出請求後,服務器端才能回復數據。
很多情況下,需要服務器端主動向客戶端推送數據,保持客戶端與服務器數據的實時與同步。此時若雙方建立的是Socket連接,服務器就可以直接將數 據傳送給客戶端;若雙方建立的是HTTP連接,則服務器需要等到客戶端發送一次請求後才能將數據傳回給客戶端,因此,客戶端定時向服務器端發送連接請求, 不僅可以保持在線,同時也是在“詢問”服務器是否有新的數據,如果有就將數據傳給客戶端。TCP(Transmission Control Protocol) 傳輸控制協議

TCP是主機對主機層的傳輸控制協議,提供可靠的連接服務,采用三次握手確認建立一個連接:

位碼即tcp標誌位,有6種標示:SYN(synchronous建立聯機) ACK(acknowledgement 確認) PSH(push傳送) FIN(finish結束) RST(reset重置) URG(urgent緊急)
Sequence number(順序號碼) Acknowledge number(確認號碼)

???

TCP是什麽?

TCP(Transmission Control Protocol 傳輸控制協議)是一種面向連接的、可靠的、基於字節流的傳輸層通信協議。

具體的關於TCP是什麽,我不打算詳細的說了;當你看到這篇文章時,我想你也知道TCP的概念了,想要更深入的了解TCP的工作,我們就繼續。它只是一個超級麻煩的協議,而它又是互聯網的基礎,也是每個程序員必備的基本功。首先來看看OSI的七層模型:
技術分享圖片
我們需要知道TCP工作在網絡OSI的七層模型中的第四層——Transport層,IP在第三層——Network層,ARP在第二層——Data Link層;在第二層上的數據,我們把它叫Frame,在第三層上的數據叫Packet,第四層的數據叫Segment。 同時,我們需要簡單的知道,數據從應用層發下來,會在每一層都會加上頭部信息,進行封裝,然後再發送到數據接收端。這個基本的流程你需要知道,就是每個數據都會經過數據的封裝和解封裝的過程。 在OSI七層模型中,每一層的作用和對應的協議如下:
技術分享圖片
TCP是一個協議,那這個協議是如何定義的,它的數據格式是什麽樣子的呢?要進行更深層次的剖析,就需要了解,甚至是熟記TCP協議中每個字段的含義。哦,來吧。
?

TCP頭部

其中 ACK SYN 序號 這三個部分在以下會用到,它們的介紹也在下面。
技術分享圖片

上面就是TCP協議頭部的格式,由於它太重要了,是理解其它內容的基礎,下面就將每個字段的信息都詳細的說明一下。

  • Source Port和Destination Port:分別占用16位,表示源端口號和目的端口號;用於區別主機中的不同進程,而IP地址是用來區分不同的主機的,源端口號和目的端口號配合上IP首部中的源IP地址和目的IP地址就能唯一的確定一個TCP連接;

  • Sequence Number:用來標識從TCP發端向TCP收端發送的數據字節流,它表示在這個報文段中的的第一個數據字節在數據流中的序號;主要用來解決網絡報亂序的問題;

  • Acknowledgment Number:32位確認序列號包含發送確認的一端所期望收到的下一個序號,因此,確認序號應當是上次已成功收到數據字節序號加1。不過,只有當標誌位中的ACK標誌(下面介紹)為1時該確認序列號的字段才有效。主要用來解決不丟包的問題;

  • Offset:給出首部中32 bit字的數目,需要這個值是因為任選字段的長度是可變的。這個字段占4bit(最多能表示15個32bit的的字,即4*15=60個字節的首部長度),因此TCP最多有60字節的首部。然而,沒有任選字段,正常的長度是20字節;

  • TCP Flags:TCP首部中有6個標誌比特,它們中的多個可同時被設置為1,主要是用於操控TCP的狀態機的,依次為URG,ACK,PSH,RST,SYN,FIN。每個標誌位的意思如下:

URG:此標誌表示TCP包的緊急指針域(後面馬上就要說到)有效,用來保證TCP連接不被中斷,並且督促中間層設備要盡快處理這些數據;

ACK:此標誌表示應答域有效,就是說前面所說的TCP應答號將會包含在TCP數據包中;有兩個取值:0和1,為1的時候表示應答域有效,反之為0;

PSH:這個標誌位表示Push操作。所謂Push操作就是指在數據包到達接收端以後,立即傳送給應用程序,而不是在緩沖區中排隊;

RST:這個標誌表示連接復位請求。用來復位那些產生錯誤的連接,也被用來拒絕錯誤和非法的數據包;

SYN:表示同步序號,用來建立連接。SYN標誌位和ACK標誌位搭配使用,當連接請求的時候,SYN=1,ACK=0;連接被響應的時候,SYN=1,ACK=1;這個標誌的數據包經常被用來進行端口掃描。掃描者發送一個只有SYN的數據包,如果對方主機響應了一個數據包回來 ,就表明這臺主機存在這個端口;但是由於這種掃描方式只是進行TCP三次握手的第一次握手,因此這種掃描的成功表示被掃描的機器不很安全,一臺安全的主機將會強制要求一個連接嚴格的進行TCP的三次握手;

FIN: 表示發送端已經達到數據末尾,也就是說雙方的數據傳送完成,沒有數據可以傳送了,發送FIN標誌位的TCP數據包後,連接將被斷開。這個標誌的數據包也經常被用於進行端口掃描。

  • Window:窗口大小,也就是有名的滑動窗口,用來進行流量控制;這是一個復雜的問題,這篇博文中並不會進行總結的;

暫時需要的信息有:

ACK : TCP協議規定,只有ACK=1時有效,也規定連接建立後所有發送的報文的ACK必須為1

SYN(SYNchronization) : 在連接建立時用來同步序號。當SYN=1而ACK=0時,表明這是一個連接請求報文。對方若同意建立連接,則應在響應報文中使SYN=1和ACK=1. 因此, SYN置1就表示這是一個連接請求或連接接受報文。

FIN (finis)即完,終結的意思, 用來釋放一個連接。當 FIN = 1 時,表明此報文段的發送方的數據已經發送完畢,並要求釋放連接。

技術分享圖片

三次握手的過程:

技術分享圖片

多麽清晰的一張圖,當然了,也不是我畫的,我也只是引用過來說明問題了。

  1. 第一次握手:建立連接。客戶端發送連接請求報文段,將SYN位置為1,Sequence Number為x;然後,客戶端進入SYN_SEND狀態,等待服務器的確認;
  2. 第二次握手:服務器收到SYN報文段。服務器收到客戶端的SYN報文段,需要對這個SYN報文段進行確認,設置Acknowledgment Number為x+1(Sequence Number+1);同時,自己自己還要發送SYN請求信息,將SYN位置為1,Sequence Number為y;服務器端將上述所有信息放到一個報文段(即SYN+ACK報文段)中,一並發送給客戶端,此時服務器進入SYN_RECV狀態;
  3. 第三次握手:客戶端收到服務器的SYN+ACK報文段。然後將Acknowledgment Number設置為y+1,向服務器發送ACK報文段,這個報文段發送完畢以後,客戶端和服務器端都進入ESTABLISHED狀態,完成TCP三次握手。
    完成了三次握手,客戶端和服務器端就可以開始傳送數據。以上就是TCP三次握手的總體介紹。

那四次分手呢?

當客戶端和服務器通過三次握手建立了TCP連接以後,當數據傳送完畢,肯定是要斷開TCP連接的啊。那對於TCP的斷開連接,這裏就有了神秘的“四次分手”。

  1. 第一次分手:主機1(可以使客戶端,也可以是服務器端),設置Sequence Number和Acknowledgment Number,向主機2發送一個FIN報文段;此時,主機1進入FIN_WAIT_1狀態;這表示主機1沒有數據要發送給主機2了;
  2. 第二次分手:主機2收到了主機1發送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number為Sequence Number加1;主機1進入FIN_WAIT_2狀態;主機2告訴主機1,我“同意”你的關閉請求;
  3. 第三次分手:主機2向主機1發送FIN報文段,請求關閉連接,同時主機2進入LAST_ACK狀態;
  4. 第四次分手:主機1收到主機2發送的FIN報文段,向主機2發送ACK報文段,然後主機1進入TIME_WAIT狀態;主機2收到主機1的ACK報文段以後,就關閉連接;此時,主機1等待2MSL後依然沒有收到回復,則證明Server端已正常關閉,那好,主機1也可以關閉連接了。

至此,TCP的四次分手就這麽愉快的完成了。當你看到這裏,你的腦子裏會有很多的疑問,很多的不懂,感覺很淩亂;沒事,我們繼續總結。

為什麽要三次握手

在謝希仁著《計算機網絡》第四版中講“三次握手”的目的是“為了防止已失效的連接請求報文段突然又傳送到了服務端,因而產生錯誤”。在另一部經典的《計算機網絡》一書中講“三次握手”的目的是為了解決“網絡中存在延遲的重復分組”的問題。

在謝希仁著《計算機網絡》書中同時舉了一個例子,如下:

“已失效的連接請求報文段”的產生在這樣一種情況下:client發出的第一個連接請求報文段並沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以後的某個時間才到達server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段後,就誤認為是client再次發出的一個新的連接請求。於是就向client發出確認報文段,同意建立連接。假設不采用“三次握手”,那麽只要server發出確認,新的連接就建立了。由於現在client並沒有發出建立連接的請求,因此不會理睬server的確認,也不會向server發送數據。但server卻以為新的運輸連接已經建立,並一直等待client發來數據。這樣,server的很多資源就白白浪費掉了。采用“三次握手”的辦法可以防止上述現象發生。例如剛才那種情況,client不會向server的確認發出確認。server由於收不到確認,就知道client並沒有要求建立連接。”

技術分享圖片

這就很明白了,防止了服務器端的一直等待而浪費資源。

為什麽要四次分手

那四次分手又是為何呢?TCP協議是一種面向連接的、可靠的、基於字節流的運輸層通信協議。TCP是全雙工模式,這就意味著,當主機1發出FIN報文段時,只是表示主機1已經沒有數據要發送了,主機1告訴主機2,它的數據已經全部發送完畢了;但是,這個時候主機1還是可以接受來自主機2的數據;當主機2返回ACK報文段時,表示它已經知道主機1沒有數據發送了,但是主機2還是可以發送數據到主機1的;當主機2也發送了FIN報文段時,這個時候就表示主機2也沒有數據要發送了,就會告訴主機1,我也沒有數據要發送了,之後彼此就會愉快的中斷這次TCP連接。如果要正確的理解四次分手的原理,就需要了解四次分手過程中的狀態變化。

  • FIN_WAIT_1: 這個狀態要好好解釋一下,其實FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態。而當對方回應ACK報文後,則進入到FIN_WAIT_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態一般是比較難見到的,而FIN_WAIT_2狀態還有時常常可以用netstat看到。(主動方)
  • FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點數據需要傳送給你(ACK信息),稍後再關閉連接。(主動方)
  • CLOSE_WAIT:這種狀態的含義其實是表示在等待關閉。怎麽理解呢?當對方close一個SOCKET後發送FIN報文給自己,你系統毫無疑問地會回應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態。接下來呢,實際上你真正需要考慮的事情是察看你是否還有數據發送給對方,如果沒有的話,那麽你也就可以 close這個SOCKET,發送FIN報文給對方,也即關閉連接。所以你在CLOSE_WAIT狀態下,需要完成的事情是等待你去關閉連接。(被動方)
  • LAST_ACK: 這個狀態還是比較容易好理解的,它是被動關閉一方在發送FIN報文後,最後等待對方的ACK報文。當收到ACK報文後,也即可以進入到CLOSED可用狀態了。(被動方)
  • TIME_WAIT: 表示收到了對方的FIN報文,並發送出了ACK報文,就等2MSL後即可回到CLOSED可用狀態了。如果FINWAIT1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。(主動方)
  • CLOSED: 表示連接中斷。

???

實例:

TCP的作用是流量控制,主要是控制數據流的傳輸。下面以瀏覽網頁為例,根據自身理解來解釋一下這個過程。(註:第二個ack屬於代碼段ack位)

握手過程中傳送的包裏不包含數據,三次握手完畢後,客戶端與服務器才正式開始傳送數據。

技術分享圖片

第一次握手:客戶端發送syn包(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認;
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。
握手過程中傳送的包裏不包含數據,三次握手完畢後,客戶端與服務器才正式開始傳送數據。理想狀態下,TCP連接一旦建立,在通信雙方中的任何一方主 動關閉連接之前,TCP 連接都將被一直保持下去。斷開連接時服務器和客戶端均可以主動發起斷開TCP連接的請求,斷開過程需要經過“四次握手”(過程就不細寫了,就是服務器和客 戶端交互,最終確定斷開)

???

對應的實例

IP 192.168.1.116.3337 > 192.168.1.123.7788: S 3626544836:3626544836
IP 192.168.1.123.7788 > 192.168.1.116.3337: S 1739326486:1739326486 ack 3626544837
IP 192.168.1.116.3337 > 192.168.1.123.7788: ack 1739326487,ack 1

第一次握手:192.168.1.116發送位碼syn=1,隨機產生seq number=3626544836的數據包到192.168.1.123,192.168.1.123由SYN=1知道192.168.1.116要求建立聯機;

第二次握手:192.168.1.123收到請求後要確認聯機信息,向192.168.1.116發送ack number=3626544837,syn=1,ack=1,隨機產生seq=1739326486的包;

第三次握手:192.168.1.116收到後檢查ack number是否正確,即第一次發送的seq number+1,以及位碼ack是否為1,若正確,192.168.1.116會再發送ack number=1739326487,ack=1,192.168.1.123收到後確認seq=seq+1,ack=1則連接建立成功。

??

我想你應該懂了

總結到這裏,也該結束了,但是對於TCP的學習遠還沒有結束。TCP是一個非常復雜的協議,這裏稍微總結了一下TCP的連接與斷開連接是發生的事情,其中還有很多的“坑”,讓我們後續有時間再繼續填吧。好了,完畢!??

通俗大白話來理解TCP協議的三次握手和四次分手