第五章 運輸層(UDP和TCP三次握手,四次揮手分析)

一杯涼茶發表於2016-11-30

    序言

        通過這章,可以知道其實三次握手和四次揮手其實真的好簡單,通過這章的學習,我相信你也會同樣的認為,以後在也不需要聽到別人問三次握手的過程而自己一臉懵逼了,覺得人家好屌,其實也就是他懂你不懂,僅此而已,不懂就去學。學了你就會覺得其實也就那樣,沒有什麼厲害的,這讓我回想以前剛學習程式設計的時候,那時候剛學C,別人就說會寫java的helloworld,真TM覺得屌啊,我連helloworld是什麼度不知道。一直羨慕人家,怎麼這麼厲害,然後自己心裡很虛,自己這麼菜啊,其實不然,不懂的就去學習,學懂了你也就沒覺得什麼了不起,所以說,不與他人相比,但求超越自己。希望能幫到現在迷茫的同學。

 

    重點在TCP的三次握手和四次揮手,還有TCP的一些特性。

                                          --WH

 

一、運輸層概述

      這一層的功能也挺簡單的,運輸層提供應用層提供端到端通訊服務,通俗的講,兩個主機通訊,也就是應用層上的程式之間的通訊,也就是轉換為程式和程式之間的通訊了,我們之前學到網路層,IP協議能將分組準確的傳送到目的主機,但是停留在網路層,並不知道要怎麼交給我們的主機應用程式,通過前面的學習,我們學習有mac地址,通過mac地址能找到同一個網路下主機,有IP地址,通過ip地址能找到不同網路下的網路,結合mac地址就能找到對應主機,那麼怎麼找到主機應用程式呢,肯定也有一個東西來標識它,那就是我們常說的了。

      埠,佔有16位,其大小也就有65536個,是從0~65535.也就是一臺計算機有65535個埠,主機之間的通訊,也就是應用程式之間的通訊,度要依靠埠,一個程式對應一個埠,程式A和程式B通訊,程式A分到的埠為60000,程式B分到的埠為60001,程式A通過埠60000傳送資料給程式B,就知道要交給60001埠,也就到了程式B中 ,這樣就達到了通訊的目的。

      熟知埠、登記埠、客戶端埠

      熟知埠:0-1023, 也就是一些固定的埠號,比如http使用的80埠,意思就是在訪問網址時,我們訪問伺服器的埠就是80,然後伺服器那邊傳網頁的資料給我們。

      登記埠:1024-49151,比如微軟開發了一個系統應用,該應用在通訊或使用時,需要使用到xxx埠,那麼就要去登記一下這個埠,以免有別人公司的應用使用同一個埠號,例如,windows系統中的3389埠,就是用來實現遠端連線的,就固定了這臺計算機如果要使用遠端連線服務,就開啟3389埠,別人就能使用遠端連線連你了,預設是不開啟的。

      客戶端埠:49152-65535,一般我們使用某個軟體,比如QQ,等其他服務,隨機拿這個範圍內的埠,而不是去拿前面哪些固定的,拿到等通訊結束後,就會釋放該埠。

 

      知道了埠是什麼?運輸層具體做了什麼事情呢?運輸層就是將兩個埠連起來通訊的介質,不然光知道兩個埠有什麼用,怎麼通訊的,還是要靠運輸層來做這個事情,其中重要的就是靠兩個協議,UDP和TCP協議。下面就來講講UDP和TCP協議的具體內容。

 

二、UDP協議

      UDP:User Datagram Protocol 使用者資料包協議。

          無連線、不可靠

          無連線:意思就是在通訊之前不需要建立連線,直接傳輸資料。

          不可靠:是將資料包的分組從一臺主機傳送到另一臺主機,但並不保證資料包能夠到達另一端,任何必須的可靠性都由應用程式提供。在 UDP 情況下,雖然可以確保傳送訊息的大小,卻不能保證訊息一定會達到目的端。沒有超時和重傳功能,當 UDP 資料封裝到 IP 資料包傳輸時,如果丟失,會傳送一個 ICMP 差錯報文給源主機。即使出現網路阻塞情況,UDP 也無法進行流量控制。此外,傳輸途中即使出現丟包,UDP 也不負責重發,甚至當出現包的到達順序雜亂也沒有糾正的功能

       

      UDP的首部格式

              

      先看UDP首部,

      源埠號:佔16位,源主機的應用程式所使用的埠號

      目標埠號:佔16位,目標主機的應用程式所使用的埠號,也就是我們需要通訊的目標程式

      UDP報長度:UDP使用者資料包的長度,資料部分+UDP首部之和為UDP報長度。

      檢驗和:檢驗和是為了提供可靠的 UDP 首部和資料而設計,這裡不要和上面的不可靠傳輸搞混淆了,這裡提供可靠的UDP首部,是因為一個程式可能接受多個程式過來的報文,那麼如何區分他們呢,就是通過5個東西來進行區分的, “源 IP 地址”、“目的 IP 地址”、“協議號”、“源埠號”、“目標埠號”的,這個檢測可靠,是檢測接受哪個正確的報文,也就是說是哪個報文要進這個埠,那個不可靠,說的是這個報文可能丟失,可能其中資料損壞了我們不關心,但是這些的前提是,你得傳輸到正確的目的地去,不然亂出亂髮資料包,豈不是亂套了。

      UDP偽首部

      就是拿到IP層的一些資料,因為要進行檢驗和,就必須要有這些資料。其中檢驗的演算法跟IP層中檢驗首部的辦法是一樣的。

 

      分析

          

 

        一個目標程式中,其中的報文,目標埠,目標ip地址肯定都市一樣的,但是源IP地址和源埠就可能不一樣,這就說明了不同源而同一目的地的報文會定位到同一佇列。這跟接下來我們要討論的TCP不一樣,因為UDP是無連線的,大家度是用這一條通道,所以其佇列中就會出現上面所說的這樣的情況。

      使用UDP協議的例子

        1、應用層協議中DNS,也就是根據域名解析ip地址的一個協議,他使用的就是UDP

        2、DHCP,這個是給各電腦分配ip地址的協議,其中用的也是UDP協議

        3、IGMP,我們說的多播,也就是使用的UDP,在多媒體教師,老師拿筆記本講課,我們在下面通過各自的電腦看到老師的畫面,這就是通過UDP傳輸資料,所以會出現有的同學卡,有的同學很流暢,就是因為其不可靠傳輸,但是卡一下,對接下來的觀看並沒有什麼映像

        還有挺多的度是用到UDP協議。

 

 

三、TCP協議

      TCP協議是面向連線的、可靠傳輸、有流量控制,擁塞控制,面向位元組流傳輸等很多優點的協議。其最終功能和UDP一樣,在端和端之間進行通訊,但是和UDP的區別還是很大的。

      TCP報文的結構

      

      1、源埠號

      2、目標埠號

      3、序列號:因為在TCP是面向位元組流的,他會將報文度分成一個個位元組,給每個位元組進行序號編寫,比如一個報文有900個位元組組成,那麼就會編成1-900個序號,然後分幾部分來進行傳輸,比如第一次傳,序列號就是1,傳了50個位元組, 那麼第二次傳,序列號就為51,所以序列號就是傳輸的資料的第一個位元組相對所有的位元組的位置。

      4、確認應答:如剛說的例子,第一次傳了50個位元組給對方,對方也會迴應你,其中帶有確認應答,就是告訴你下一次要傳第51個位元組來了,所以這個確認應答就是告訴對方要傳第多少個位元組了

      5、首部長度:就是首部的長度,

      6、保留:給以後有需要在用,這個保留的位置放的東西是跟控制位類似的

      7、控制位:目前有的控制位為6個

          URG:緊急,當URG為1時,表名緊急指標欄位有效,標識該報文是一個緊急報文,傳送到目標主機後,不用排隊,應該讓該報文儘量往下排,讓其早點讓應用程式給接受。

          ACK:確認,當ACK為1時,確認序號才有效。當ACK為0時,確認序號沒用

          PSH:推送,當為1時,當遇到此報文時,會減少資料向上交付,本來想應用程式交付資料是要等到一定的快取大小才傳送的,但是遇到它,就不用在等足夠多的資料才向上交付,而是讓應用程式早點拿到此報文,這個要和緊急分清楚,緊急是插隊,但是提交快取大小的資料不變,這個推送就要排隊,但是遇到他的時候,會減少交付的快取資料,提前交付。

          RST:復位,報文遇到很嚴重的差錯時,比如TCP連線出錯等,會將RST置為1,然後釋放連線,全部重新來過。

          SYN:同步,在進行連線的時候,也就是三次握手時用得到,下面會具體講到,配合ACK一起使用

          FIN:終止,在釋放連線時,也就是四次揮手時用的。

      8、視窗:指傳送報文段一方的接受視窗大小,用來控制對方傳送的資料量(從確認號開始,允許對方傳送的資料量)。也就是後面需要講的滑動視窗的視窗大小

      9、檢驗和:檢驗首部和資料這兩部分,和UDP一樣,需要拿到偽首部中的資料來幫助檢測

      10、選項:長度可變,介紹一種選項,最大報文段長度,MSS。 能夠告訴對方TCP,我的快取能接受報文段的資料欄位的最大長度是MSS個位元組。如果沒有使用選項,那麼首部固定是20個位元組。

      11、填充:就是為了讓其成為整數個位元組

 

 

      面向連線

      (三次握手):在通訊之前,會先通過三次握手的機制來確認兩埠之間的連線是否可用。而UDP不需要確認是否可用,直接傳。

          三次握手機制。

                

      一開始客戶端和服務端都市關閉狀態,但是在某個時刻,客戶端需要和服務端進行通訊,此時雙方都會各自準備好埠,伺服器段的埠會處於監聽狀態,等待客戶端的連線。客戶端可會知道自己的埠號,和目的程式的埠號,這樣才能發起請求。

      第一次握手:客戶端想與伺服器進行連線了,所以狀態變為主動開啟,同時傳送一個連線請求報文給伺服器段SYN=1,並且會攜帶x個位元組過去。傳送完請求連線報文後,客戶端的狀態就變為了SYN_SENT,可以說這個狀態是等待傳送確認(為了傳送第三次握手時的確認包)

      第二次握手:服務端接收到連線請求報文後,從LSTTEN狀態變為被動開啟狀態,然後給客戶端返回一個報文。這個報文有兩層意思,一是確認報文,而可以達到告訴客戶端,我也開啟連線了。發完後,變為SYN_RCVD狀態(也可以說是等待接受確認狀態,接受客戶端發過來的確認包)

      第三次握手:客戶端得到伺服器端的確認和知道伺服器端也已經準備好了連線後,還會發一個確認報文到伺服器端,告訴伺服器端,我接到了你傳送的報文,接下來就讓我們兩個進行連線了。客戶端傳送完確認報文後,進入ESTABLISHED,而伺服器接到了,也變為ESTABLISHED

      進入到ESTABLISHED狀態後,連線就已經完成了,可以進行通訊了。

      問題:為什麼需要第三次握手,有前面兩次不就已經可以了嗎?

          假設沒有第三次握手,客戶端傳送一個連線請求報文過去,但是因為網路延遲,在等待了一個超時時間後,客戶端就會在重新發一個請求連線報文過去,然後正常的進行,伺服器端發回一個確認連線報文,然後就開始通訊,通訊結束後,那個第一次因為網路延遲的請求連線報文到了伺服器端,伺服器端不知道這個報文已經失效,也發回了一個確認連線報文,客戶端接收後,發現自己並沒有傳送連線請求(因為超時了,所以就認為自己沒有發),所以對這個確認連線請求就什麼也不做,但是此時客戶端不這麼認為,他認為i連線已經建立了,就一直開啟著等待客戶端傳資料過來,這就造成了極大的浪費。如果有了第三次握手,那麼客戶端就可以通知伺服器了。所以第三次握手也很重要。

 

      同時開啟連線請求

          正常情況下,通訊一方請求建立連線,另一方響應該請求,但是如果出現,通訊雙方同時請求建立連線時,則連線建立過程並不是三次握手過程,而且這種情況的連線也只有一條,並不會建立兩條連線。同時開啟連線時,兩邊幾乎同時傳送 SYN,並進入 SYN_SENT 狀態,當每一端收到 SYN 時,狀態變為 SYN_RCVD,同時雙方都再發 SYN 和 ACK 作為對收到的 SYN 進行確認應答。當雙方都收到 SYN 及相應的 ACK 時,狀態變為 ESTABLISHED

            

      可靠傳輸

          通過1、資料編號和積累確認 2、以位元組為單位的滑動視窗 3、超時重傳時間 4、快速重傳 這四個方面來達到可靠傳輸的目的。

          1、資料編號:將每個位元組進行編號,有900個位元組,就從1到900進行編號

          1、積累確認:伺服器端不是接收到一個位元組就發一個確認,那樣效率太低,而是當接收到4,5個時,在傳送一個確認,那麼在之前的確認之前的資料就算髮送成功了的。

          2、滑動視窗:這個跟在資料鏈路層講個滑動視窗一樣。每次能傳送的資料是在此視窗中的,接到了多少資料,就往後滑多少資料

          3、超時重傳時間:這個也在鏈路層講過,如果等待一段時間後,還沒接收到確認報文,那麼就重新傳

          4、快速重傳:在滑動視窗中的應用,比如傳了1234 6到伺服器端,老辦法是在4之後的所有資料度要重新傳,而這個快速重傳就只需要等待傳了5這個序號,就可以繼續往下接收資料了。

         

      流量控制

          在傳輸層中,有接受快取和傳送快取這兩個東西的存在,所以每次傳送資料過去另一端時,都會把這些資料給帶過去,讓對方知道自己的這兩個快取的大小,然後來合理的設定自己的傳送視窗的大小,如果對方的快取快滿了,對方在傳送資料過來的時候,就會告訴自己,少發一點資料過來,自己就設定滑動視窗小一點,讓對方有緩衝的機會,而不會導致快取溢位,不讓自己的報文被丟棄。

 

      擁塞控制

          其實跟流量控制差不多,但是站的角度更大,此時既考慮了對方接收不過來,快取太多溢位導致,又考慮線上路中,線路上的傳輸速率就那麼大,但是有很多人同時用,傳送的資料太多,就會使線路發現擁塞,也就是路由器可能轉發不過來,導致大量資料丟失,這兩個問題。所以擁塞控制這個解決方案,大概意思就是當檢測到有網路擁塞時,就會讓自己的滑動視窗變小,但具體是怎麼變化的,就是根據演算法來算了,

            傳送視窗的上限值 = Min[rwnd,cwnd]    

            rwnd:接受視窗,根據接受快取,而定的接受視窗,接收快取還有很多,那麼接收視窗就大

             cwnd:擁塞視窗,根據線路中的擁塞狀況來決定,線路中不擁塞,那麼此視窗就大,

            傳送視窗是取兩個中較小值。這個還是可以理解的。

      慢啟動演算法、快速恢復演算法、結合來達到對擁塞進行控制的,想了解這兩種演算法的,百度一下百度百科

 

      TCP釋放連線時的四次揮手

        通訊完成後,連線就會被釋放,通過四次揮手機制來完成這個事情。(畫來畫去還是覺得官方的圖好。)

        

 

        第一次揮手:從ESTABLISHED變為主動關閉狀態,客戶端主動傳送釋放連線請求給伺服器端,FIN=1。傳送完之後就變為FIN_WAIT_1狀態,這個狀態可以說是等待確認狀態。

        第二次揮手:伺服器接收到客戶端發來的釋放連線請求後,狀態變為CLOSE_WAIT,然後傳送確認報文給客戶端,告訴他我接收到了你的請求。為什麼變為CLOSE_WAIT,原因是是客戶端傳送的釋放連線請求,可能自己這端還有資料沒有傳送完呢,所以這個時候整個TCP連線的狀態就變為了半關閉狀態。伺服器端還能傳送資料,並且客戶端也能接收資料,但是客戶端不能在傳送資料了,只能夠傳送確認報文。客戶端接到伺服器的確認報文後,就進入了FIN_WAIT_2

狀態。也可以說這是等待伺服器釋放連線狀態。

        第三次揮手:伺服器端所有的資料度傳送完了,認為可以關閉連線了,狀態變為被動關閉,所以向客戶端傳送釋放連線報文,發完之後自己變為LAST_WAIT狀態,也就是等待客戶端確認狀態

        第四次揮手:客戶端接到釋放連線報文後,傳送一個確認報文,然後自己變為TIME_WAIT,而不是立馬關閉,因為客戶端傳送的確認報文可能會丟失,丟失的話伺服器就會重傳一個FIN,也就是釋放連線報文,這個時候客戶端必須還沒關閉。 當伺服器接受到確認報文後,伺服器就進入CLOSE狀態,也就是關閉了。但是由於上面說的這個原因,客戶端必須等待一定的時間才能夠進入CLOSE狀態。

  

        上面就是TCP連線釋放的四次揮手機制。很簡單把。

 

        同時關閉連線

        正常情況下,通訊一方請求連線關閉,另一方響應連線關閉請求,並且被動關閉連線。但是若出現同時關閉連線請求時,通訊雙方均從 ESTABLISHED 狀態轉換為 FIN_WAIT_1 狀態。任意一方收到對方發來的 FIN 報文段後,其狀態均由 FIN_WAIT_1轉變到 CLOSING 狀態,併傳送最後的 ACK 資料段。當收到最後的 ACK 資料段後,狀態轉變化 TIME_WAIT,在等待 2MSL 時間後進入到 CLOSED 狀態,最終釋放整個 TCP 傳輸連線。其過程入下

                  

 

 

        舉一個使用tcp的例子,一般需要保證資料可靠時,度會使用tcp協議。

          1、http協議進行網站的訪問時,使用的就是tcp。

          

 

相關文章