天天看點

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

    序言

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

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

                                          --WZY

一、運輸層概述

      這一層的功能也挺簡單的,運輸層提供應用層提供端到端通信服務,通俗的講,兩個主機通訊,也就是應用層上的程序之間的通信,也就是轉換為程序和程序之間的通信了,我們之前學到網絡層,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。