NO IMAGE

640.gif?wxfrom=5&wx_lazy=1

本文來自作者 宋璐 在 GitChat 上分享「如何快速入門網路基礎知識(TCP/IP
和 HTTP)」,「閱讀原文」檢視交流實錄

「文末高能」

編輯 | 嘉仔

傳輸層概

  • 作用:傳輸層為它上面的應用層提供通訊服務。

  • 在OSI七層參考模型中,傳輸層是面向通訊的最高層,也是使用者功能的最底層。

  • 傳輸層兩大重要的功能:複用 和 分用。

    • 複用:在傳送端,多個應用程序公用一個傳輸層;

    • 分用:在接收端,傳輸層會根據埠號將資料分派給不同的應用程序。

  • 和網路層的區別:

    • 網路層為不同主機提供通訊服務,而傳輸層為不同主機的不同應用提供通訊服務。

    • 網路層只對報文頭部進行差錯檢測,而傳輸層對整個報文進行差錯檢測。

UDP(使用者資料包協議)詳解

UDP的特點

  1. UDP只在IP資料包服務的基礎上增加了少量的功能:複用與分用、對整個報文的差錯檢測。

  2. UDP是無連線的

    通訊前不需要建立連線,通訊結束也無需釋放連線。

  3. UDP是不可靠的

    它是盡力而為交付,不能確保每一個資料包都送達。

  4. UDP是面向報文的

    所謂『面向報文』就是指:UDP資料傳輸的單位是報文,且不會對資料作任何 拆分 和 拼接 操作。

    在傳送端,應用程式給傳輸層的UDP什麼樣的資料,UDP不會對資料進行切分,只增加一個UDP頭並交給網路層。

    在接收端,UDP收到網路層的資料包後,去除IP資料包頭部後遍交給應用層,不會作任何拼接操作。

  5. UDP沒有擁塞控制

    UDP始終以恆定的速率傳送資料,並不會根據網路擁塞情況對傳送速率作調整。這種方式有利有弊。

    弊端:網路擁塞時有些報文可能會丟失,因此UDP不可靠。

    優點:有些使用場景允許報文丟失,如:直播、語音通話,但對實時性要求很高,此時UDP還是很有用武之地的。

  6. UDP支援一對一、一對多、多對多、多對一通訊

    而TCP只支援一對一通訊。

  7. UDP首部開銷小,只有8位元組。

    而TCP頭部至少由20位元組,相比於TCP要高效很多。

PS:問:UDP不可靠具體體現在哪些方面?資料包丟失?資料包順序?

UDP報文頭

0?wx_fmt=png

  • 源埠

  • 目的埠

  • 長度:整個資料包的長度

  • 檢驗和:整個資料包的檢驗和。

TCP(傳輸控制協議)詳解

TCP特點

  1. TCP是面向連線的

    通訊前需要建立連線,通訊結束需要釋放連線。

  2. TCP提供可靠交付服務

    所謂『可靠』指的是:TCP傳送的資料無重複、無丟失、無錯誤、與傳送端順序一致。

  3. TCP是面向位元組流的

    所謂『面向位元組流』指的是:TCP以位元組為單位。雖然傳輸的過程中資料被劃分成一個個資料包,但這只是為了方便傳輸,接收端最終接受到的資料將與傳送端的資料一模一樣。

  4. TCP提供全雙工通訊

    所謂『全雙工通訊』指的是:TCP的兩端既可以作為傳送端,也可以作為接收端。

  5. 一條TCP連線的兩端只能有兩個端點

    TCP只能提供點到點的通訊,而UDP可以任意方式的通訊。

TCP連線
與 套接字

  • 什麼是『TCP連線』?

    TCP連線是一種抽象的概念,表示一條可以通訊的鏈路。每條TCP連線有且僅有兩個端點,表示通訊的雙方。且雙發在任意時刻都可以作為傳送者和接收者。

  • 什麼是『套接字』?

    一條TCP連線的兩端就是兩個套接字。套接字=IP地址: 埠號。因此,TCP連線=(套接字1,套接字2)=(IP1:埠號1,IP2:埠號2)

TCP頭部

0?wx_fmt=png

TCP頭部長度有20位元組的固定部分,選項部分長度不定,但最多40位元組,因此TCP頭部在20-60位元組之間。

  1. 源埠 和 目的埠

    傳輸層和網路層一大重要區別就是傳輸層指定了資料包發往的應用程序,因此需要埠號標識。

  2. 序號

    當前TCP資料包資料部分的第一個位元組的序號。我們知道,TCP是面向位元組的,它會對傳送的每一個位元組進行編號,而且不同資料包之間是連續編號的。

    由於本欄位4位元組,可以給[0,2^32-1]個位元組進行編號(大約4G),而且序號迴圈使用,當傳送完2^32-1個位元組後,序號又從0開始。一般來說,當2^32-1個位元組被髮送的時候,前面的位元組早就傳送成功了,因此序號可以迴圈使用。

  3. 確認號

    表示當前主機作為接收端時,期望接收的下一個位元組的編號是多少。也表示,當前主機已經正確接收的最後一個位元組序號 1。

  4. 資料偏移(報文長度)

    它表明了資料包頭部的長度。

  5. 保留欄位

  6. 識別符號

    TCP有7種識別符號,用於表示TCP報文的性質。它們只能為0或1。

  • URG=1
    當URG欄位被置1,表示本資料包的資料部分包含緊急資訊,此時緊急指標有效。緊急資料一定位於當前資料包資料部分的最前面,緊急指標標明瞭緊急資料的尾部。如control c:這個命令要求作業系統立即停止當前程序。此時,這條命令就會存放在資料包資料部分的開頭,並由緊急指標標識命令的位置,並URG欄位被置1。

  • ACK=1
    ACK被置1後確認號欄位才有效。此外,TCP規定,在連線建立後傳送的所有報文段都必須把ACK置1。

  • PSH=1
    當接收方收到PSH=1的報文後,會立即將資料交付給應用程式,而不會等到緩衝區滿後再提交。一些互動式應用需要這樣的功能,降低命令的響應時間。

  • RST=1
    當該值為1時,表示當前TCP連線出現嚴重問題,必須要釋放重連。

  • SYN=1
    SYN在建立連線時使用。當SYN=1,ACK=0時,表示當前報文段是一個連線請求報文。當SYN=1,ACK=1時,表示當前報文段是一個同意建立連線的應答報文。

  • FIN=1
    FIN=1表示此報文段是一個釋放連線的請求報文。

  1. 接收視窗大小

    該欄位用於實現TCP的流量控制。它表示當前接收方的接收視窗的剩餘容量,傳送方收到該值後會將傳送視窗調整成該值的大小。傳送視窗的大小又決定了傳送速率,所以接收方通過設定該值就可以控制傳送放的傳送速率。傳送方每收到一個資料包都要調整當前的傳送視窗。

  2. 檢驗和

    用於接收端檢驗整個資料包在傳輸過程中是否出錯。

  3. 緊急指標

    用於標識緊急資料的尾部。

  4. 選項欄位

    上述欄位都是每個TCP頭部必須要有的,而選項欄位是可選的,且長度可變,最長40位元組。
    最常用的選項欄位為MMS:最大報文長度。

TCP三次握手

0?wx_fmt=png

PS:TCP協議中,主動發起請求的一端稱為『客戶端』,被動連線的一端稱為『服務端』。不管是客戶端還是服務端,TCP連線建立完後都能傳送和接收資料。

起初,伺服器和客戶端都為CLOSED狀態。在通訊開始前,雙方都得建立各自的傳輸控制塊(TCB)。
伺服器建立完TCB後遍進入LISTEN狀態,此時準備接收客戶端發來的連線請求。

第一次握手

客戶端向服務端傳送連線請求報文段。該報文段的頭部中SYN=1,ACK=0,seq=x。請求傳送後,客戶端便進入SYN-SENT狀態。

  • PS1:SYN=1,ACK=0表示該報文段為連線請求報文。

  • PS2:x為本次TCP通訊的位元組流的初始序號。
    TCP規定:SYN=1的報文段不能有資料部分,但要消耗掉一個序號。

第二次握手

服務端收到連線請求報文段後,如果同意連線,則會傳送一個應答:SYN=1,ACK=1,seq=y,ack=x 1。該應答傳送完成後便進入SYN-RCVD狀態。

  • PS1:SYN=1,ACK=1表示該報文段為連線同意的應答報文。

  • PS2:seq=y表示服務端作為傳送者時,傳送位元組流的初始序號。

  • PS3:ack=x 1表示服務端希望下一個資料包傳送序號從x 1開始的位元組。

第三次握手

當客戶端收到連線同意的應答後,還要向服務端傳送一個確認報文段,表示:服務端發來的連線同意應答已經成功收到。該報文段的頭部為:ACK=1,seq=x 1,ack=y 1。

客戶端發完這個報文段後便進入ESTABLISHED狀態,服務端收到這個應答後也進入ESTABLISHED狀態,此時連線的建立完成!

為什麼連線建立需要三次握手,而不是兩次握手?

防止失效的連線請求報文段被服務端接收,從而產生錯誤。

PS:失效的連線請求:若客戶端向服務端傳送的連線請求丟失,客戶端等待應答超時後就會再次傳送連線請求,此時,上一個連線請求就是『失效的』。

若建立連線只需兩次握手,客戶端並沒有太大的變化,仍然需要獲得服務端的應答後才進入ESTABLISHED狀態,而服務端在收到連線請求後就進入ESTABLISHED狀態。此時如果網路擁塞,客戶端傳送的連線請求遲遲到不了服務端,客戶端便超時重發請求,如果服務端正確接收並確認應答,雙方便開始通訊,通訊結束後釋放連線。此時,如果那個失效的連線請求抵達了服務端,由於只有兩次握手,服務端收到請求就會進入ESTABLISHED狀態,等待傳送資料或主動傳送資料。但此時的客戶端早已進入CLOSED狀態,服務端將會一直等待下去,這樣浪費服務端連線資源。

TCP四次揮手

0?wx_fmt=png

TCP連線的釋放一共需要四步,因此稱為『四次揮手』。我們知道,TCP連線是雙向的,因此在四次揮手中,前兩次揮手用於斷開一個方向的連線,後兩次揮手用於斷開另一方向的連線。

第一次揮手

若A認為資料傳送完成,則它需要向B傳送連線釋放請求。該請求只有報文頭,頭中攜帶的主要引數為:FIN=1,seq=u。此時,A將進入FIN-WAIT-1狀態。

  • PS1:FIN=1表示該報文段是一個連線釋放請求。

  • PS2:seq=u,u-1是A向B傳送的最後一個位元組的序號。

第二次揮手

B收到連線釋放請求後,會通知相應的應用程式,告訴它A向B這個方向的連線已經釋放。此時B進入CLOSE-WAIT狀態,並向A傳送連線釋放的應答,其報文頭包含:ACK=1,seq=v,ack=u 1。

  • PS1:ACK=1:除TCP連線請求報文段以外,TCP通訊過程中所有資料包的ACK都為1,表示應答。

  • PS2:seq=v,v-1是B向A傳送的最後一個位元組的序號。

  • PS3:ack=u 1表示希望收到從第u 1個位元組開始的報文段,並且已經成功接收了前u個位元組。

A收到該應答,進入FIN-WAIT-2狀態,等待B傳送連線釋放請求。

第二次揮手完成後,A到B方向的連線已經釋放,B不會再接收資料,A也不會再傳送資料。但B到A方向的連線仍然存在,B可以繼續向A傳送資料。

第三次揮手

當B向A發完所有資料後,向A傳送連線釋放請求,請求頭:FIN=1,ACK=1,seq=w,ack=u 1。B便進入LAST-ACK狀態。

第四次揮手

A收到釋放請求後,向B傳送確認應答,此時A進入TIME-WAIT狀態。該狀態會持續2MSL時間,若該時間段內沒有B的重發請求的話,就進入CLOSED狀態,撤銷TCB。當B收到確認應答後,也便進入CLOSED狀態,撤銷TCB。

為什麼A要先進入TIME-WAIT狀態,等待2MSL時間後才進入CLOSED狀態?

為了保證B能收到A的確認應答。若A發完確認應答後直接進入CLOSED狀態,那麼如果該應答丟失,B等待超時後就會重新傳送連線釋放請求,但此時A已經關閉了,不會作出任何響應,因此B永遠無法正常關閉。

TCP可靠傳輸的實現

TCP的可靠性表現在:它嚮應用層提供的資料是 無差錯的、有序的、無丟失的,簡單的說就是:TCP最終遞交給應用層的資料和傳送者傳送的資料是一模一樣的。TCP採用了流量控制、擁塞控制、連續ARQ等技術來保證它的可靠性。

PS:網路層傳輸的資料單元為『資料包』,傳輸層的資料單元為『報文段』,但為了方便起見,可以統稱為『分組』。

停止等待協議(ARQ協議)

TCP保證其可靠性採用的是更為複雜的滑動視窗協議,但停止等待協議是它的簡化版,為了方便理解,這裡先介紹停止等待協議。

  • AQR協議

    ARQ(Automatic Repeat reQuest)自動重傳請求。顧名思義,當請求失敗時它會自動重傳,直到請求被正確接收為止。這種機制保證了每個分組都能被正確接收。停止等待協議是一種ARQ協議。

  • 停止等待協議的原理

    • 無差錯的情況

      A向B每傳送一個分組,都要停止傳送,等待B的確認應答;A只有收到了B的確認應答後才能傳送下一個分組。

    • 分組丟失和出現差錯的情況

      傳送者擁有超時計時器。每傳送一個分組便會啟動超時計時器,等待B的應答。若超時仍未收到應答,則A會重發剛才的分組。

      分組出現差錯:若B收到分組,但通過檢查和欄位發現分組在運輸途中出現差錯,它會直接丟棄該分組,並且不會有任何其他動作。A超時後便會重新傳送該分組,直到B正確接收為止。

      分組丟失:若分組在途中丟失,B並沒有收到分組,因此也不會有任何響應。當A超時後也會重傳分組,直到正確接收該分組的應答為止。

      綜上所述:當分組丟失 或 出現差錯 的情況下,A都會超時重傳分組。

    • 應答丟失 和 應答遲到 的情況

      TCP會給每個位元組都打上序號,用於判斷該分組是否已經接收。

      應答丟失:若B正確收到分組,並已經返回應答,但應答在返回途中丟失了。此時A也收不到應答,  從而超時重傳。緊接著B又收到了該分組。接收者根據序號來判斷當前收到的分組是否已經接收,若已接收則直接丟棄,並補上一個確認應答。

      應答遲到:若由於網路擁塞,A遲遲收不到B傳送的應答,因此會超時重傳。B收到該分組後,發現已經接收,便丟棄該分組,並向A補上確認應答。A收到應答後便繼續傳送下一個分組。但經過了很長時間後,那個失效的應答最終抵達了A,此時A可根據序號判斷該分組已經接收,此時只需簡單丟棄即可。

  • 停止等待協議的注意點

    • 每傳送完一個分組,該分組必須被保留,直到收到確認應答為止。

    • 必須給每個分組進行編號。以便按序接收,並判斷該分組是否已被接收。

    • 必須設定超時計時器。每傳送一個分組就要啟動計時器,超時就要重發分組。

    • 計時器的超時時間要大於應答的平均返回時間,否則會出現很多不必要的重傳,降低傳輸效率。但超時時間也不能太長。

滑動視窗協議(連續ARQ協議)

  • 連續ARQ協議

    在ARQ協議傳送者每次只能傳送一個分組,在應答到來前必須等待。而連續ARQ協議的傳送者擁有一個傳送視窗,傳送者可以在沒有得到應答的情況下連續傳送視窗中的分組。這樣降低了等待時間,提高了傳輸效率。

  • 累計確認

    在連續ARQ協議中,接收者也有個接收視窗,接收者並不需要每收到一個分組就返回一個應答,可以連續收到分組之後統一返回一個應答。這樣能節省流量。TCP頭部的ack欄位就是用來累計確認,它表示已經確認的位元組序號 1,也表示期望傳送者傳送的下一個分組的起始位元組號。

  • 傳送視窗
    0?wx_fmt=png

    傳送視窗的大小由接收視窗的剩餘大小決定。接收者會把當前接收視窗的剩餘大小寫入應答TCP報文段的頭部,傳送者收到應答後根據該值和當前網路擁塞情況設定傳送視窗的大小。傳送視窗的大小是不斷變化的。傳送視窗由三個指標構成:

    傳送者每收到一個應答,後沿就可以向前移動指定的位元組。此時若視窗大小仍然沒變,前沿也可以向前移動指定位元組。當p2和前沿重合時,傳送者必須等待確認應答。

    • p1
      p1指向傳送視窗的後沿,它後面的位元組表示已經傳送且已收到應答。

    • p2
      p2指向尚未傳送的第一個位元組。p1-p2間的位元組表示已經傳送,但還沒收到確認應答。這部分的位元組仍需保留,因為可能還要超時重發。p2-p3間的位元組表示可以傳送,但還沒有傳送的位元組。

    • p3
      p3指向傳送視窗的前沿,它前面的位元組尚未傳送,且不允許傳送。

  • 接收視窗

    0?wx_fmt=png

  • 接收者收到的位元組會存入接收視窗,接收者會對已經正確接收的有序位元組進行累計確認,傳送完確認應答後,接收視窗就可以向前移動指定位元組。

    如果某些位元組並未按序收到,接收者只會確認最後一個有序的位元組,從而亂序的位元組就會被重新傳送。

  • 連續ARQ的注意點

  1. 同一時刻傳送視窗的大小並不一定和接收視窗一樣大。雖然傳送視窗的大小是根據接收視窗的大小來設定的,但應答在網路中傳輸是有時間的,有可能t1時間接收視窗大小為m,但當確認應答抵達傳送者時,接收視窗的大小已經發生了變化。此外傳送視窗的大小還隨網路擁塞情況影響。當網路出現擁塞時,傳送視窗將被調小。

  2. TCP標準並未規定未按序到達的位元組的處理方式。但TCP一般都會快取這些位元組,等缺少的位元組到達後再交給應用層處理。這比直接丟棄亂序的位元組要節約頻寬。

  3. TCP標準規定接收方必須要有累計確認功能。接收方可以對多個TCP報文段同時確認,但不能拖太長時間,一般是0.5S以內。此外,TCP允許接收者在有資料要傳送的時候捎帶上確認應答。但這種情況一般較少,因為一般很少有兩個方向都要傳送資料的情況。

流量控制

  • 什麼是流量控制?

    如果傳送者傳送過快,接收者來不及接收,那麼就會有分組丟失。為了避免分組丟失,控制傳送者的傳送速度,使得接收者來得及接收,這就是流量控制。

  • 流量控制的目的?

    流量控制根本目的是防止分組丟失,它是構成TCP可靠性的一方面。

  • 如何實現流量控制?

    由滑動視窗協議(連續ARQ協議)實現。滑動視窗協議既保證了分組無差錯、有序接收,也實現了流量控制。

  • 流量控制引發的死鎖

    當傳送者收到了一個視窗為0的應答,傳送者便停止傳送,等待接收者的下一個應答。但是如果這個視窗不為0的應答在傳輸過程丟失,傳送者一直等待下去,而接收者以為傳送者已經收到該應答,等待接收新資料,這樣雙方就相互等待,從而產生死鎖。

  • 持續計時器

    為了避免流量控制引發的死鎖,TCP使用了持續計時器。每當傳送者收到一個零視窗的應答後就啟動該計時器。時間一到便主動傳送報文詢問接收者的視窗大小。若接收者仍然返回零視窗,則重置該計時器繼續等待;若視窗不為0,則表示應答報文丟失了,此時重置傳送視窗後開始傳送,這樣就避免了死鎖的產生。

擁塞控制

  • 擁塞控制
    和 流量控制 的區別?

    PS:擁塞控制是針對於網路而言的,它是防止往網路中寫入太多分組,從而導致網路擁塞的情況;而流量控制是針對接收者的,它是通過控制傳送者的傳送速度保證接收者能夠來得及接收。

  1. 擁塞控制:擁塞控制是作用於網路的,它是防止過多的資料注入到網路中,避免出現網路負載過大的情況;

  2. 流量控制:流量控制是作用於接收者的,它是控制傳送者的傳送速度從而使接收者來得及接收。

擁塞控制的目的?

  1. 緩解網路壓力

  2. 保證分組按時到達

慢開始演算法
和 擁塞避免演算法

  • 加法增加:指的是擁塞避免演算法,使得傳送視窗以線性的方式增長;

  • 乘法減小:指的是不管當前正使用慢開始演算法還是擁塞避免演算法,只要發生擁塞時,慢開始門限將會變成當前視窗的一半。

  • 傳送方維護一個傳送視窗,傳送視窗的大小取決於網路的擁塞情況和接收視窗的大小,傳送視窗是動態變化的。

  • 傳送方還維護一個慢開始門限

  • 演算法的具體過程:

  • 慢開始演算法的作用:慢開始演算法將傳送視窗從小擴大,而且按指數級擴大,從而避免一開始就往網路中注入過多的分組從而導致擁塞;它將視窗慢慢擴大的過程其實也在探測網路擁塞情況的過程,當發現出現擁塞時,及時降低傳送速度,從而減緩網路擁塞。

  • 擁塞避免演算法的作用:擁塞避免演算法使傳送視窗以線性方式增長,而非指數級增長,從而使網路更加不容易發生擁塞。

  • AIMD演算法(加法增大乘法減小演算法)。慢開始演算法 和 擁塞避免演算法 還有個名稱叫做『加法增大乘法減小演算法』。

  1. 通訊開始時,傳送方的傳送視窗設為1,併傳送第一個分組M1;

  2. 接收方收到M1後,返回確認應答,此時傳送方傳送視窗擴大兩倍,併傳送M2、M3;(即,傳送方每次收到確認應答後,都將傳送視窗設為當前值的兩倍)

  3. 若傳送視窗>慢開始門限,則使用擁塞避免演算法,每次收到確認應答後都將傳送視窗 1;

  4. 若傳送方出現了超時重傳,則表明網路出現擁塞,此時:
    a)慢開始門限設為當前傳送視窗的一半
    b)傳送視窗設為1
    c)啟用擁塞避免演算法

    PS:傳送超時重傳時,傳送視窗有可能已經超過了慢開始門限,也有可能還沒超過;此時不管何種情況,都一律啟用擁塞避免演算法,並執行上述三步操作!

  1. 傳送視窗 < 慢開始門限:使用慢開始演算法

  2. 傳送視窗 > 慢開始門限:使用擁塞避免演算法

  3. 傳送視窗 = 慢開始門限:使用慢開始演算法或擁塞避免演算法

快重傳演算法
和 快恢復演算法

  • 上述慢開始演算法和擁塞避免演算法能保證網路出現擁塞時進行相應的處理,而快重傳和快恢復是一種擁塞預防的方式,此時網路可能尚未出現擁塞,但已經有擁塞的徵兆,因此得作出一些預防措施。

  • 快重傳原理:因為TCP具有累計確認的能力,因此接收者收到一個分組的時候不會立即發出應答,可能需要等待收到多個分組之後再同一發出累計確認。但快重傳演算法就要求,接收者如果接收到一個亂序的分組的話,就必須立即發出前一個正確分組的確認應答,這樣能讓傳送者儘早地知道有一個分組可能丟失。

  • 快恢復原理:當傳送者收到同一個分組的三個確認應答後,就基本可以判斷這個分組已經丟失了;這時候無需等待超時,直接執行『乘法減小加法增大』:

  1. 將慢開始門限減半

  2. 將傳送視窗減半(不設為1)

  3. 使用擁塞避免演算法


近期熱文

Java
多執行緒程式設計核心技術有哪些

Python
的 C 擴充套件開發慣例

如何成為一名程式設計師麵霸

輕鬆入門
| 用 WordPress 和主題模板做網站

Java
8 Stream API 實用指南


福利

640?wx_fmt=png

「閱讀原文」看交流實錄,你想知道的都在這裡