1. 程式人生 > >【網路】基礎複習

【網路】基礎複習

複習的起點:網路協議的體系結構;

OSI七層協議和TCP/IP四層協議

OSI七層協議

從上往下:應用層,表示層,會話層,傳輸層,網路層,資料鏈路層,物理層;

OSI七層協議是用來學習的協議模型,在實際使用中使用的基本都是TCP/IP四層協議;

前三層只學習應用層:即使用者使用,如http,ftp等協議;
傳輸層: TCP、UDP 都是傳輸層的協議,不過兩者有很大的區別,後面細細複習;
網路層:負責不同主機的通訊服務,使用的是IP協議;
資料鏈路層:資料總是在一段一段的鏈路上傳輸,所以規定了協議,其中在OSI七層協議中ARP協議屬於資料鏈路層;
物理層:字面上的物理,就是傳統意義上的物理裝置的連結;

而實際通訊的過程中,資料是通過貫穿協議棧的方式進行資料的封裝和傳送的,這個封包和解包的具體過程在下面複習;

TCP/IP四層協議

從上往下:應用層,傳輸層,網際層,網路介面層;

TCP/IP四層協議將OSI七層協議的上三層和下兩層都進行了合併,就成為了現在的四層協議,其中OSI的應用層,表示層和會話層合併為了TCP/IP的應用層,OSI的資料鏈路層和物理層合併為TCP/IP的網路介面層;

在複習OSI七層協議的時候,我們說到資料的傳輸過程是貫穿協議棧的,在傳送和接受方不斷的封包和解包的; 核心的資料一直被包裹在其中,只不過在路過每一層的時候都要被打上那一層的標籤,所謂通關文牒,也就是每一層的幀格式,下面就TCP/IP四層協議每一層的幀格式來複習;(我以為這個大概瞭解就好了,就在我面騰訊的時候,居然讓我把每一層的格式說出來,更有甚者,讓我直接說出TCP的報頭長度,可見現在找工作的不容易,面試官使出渾身解數啊,至於能不能記下,就看各位共同奮鬥的同志的造化了);

乙太網幀格式:

源MAC地址,目的MAC地址,型別,資料,幀校驗

在網路層,IP協議是最主要的協議,配套的還有ARP, ICMP, IGMP 協議;

IP資料報格式:
這裡寫圖片描述

版本:佔4位,指IP協議的版本,IPV4或者IPV6;
首部長度:佔四位,5~15之間,即首部長度最小為20個位元組,最大為60個位元組,當首部長度不是4的倍數的時候就用到了最後的填充欄位;
服務型別:佔8位,一般情況不使用;
總長度: 指首部和資料的總長度,佔16位;

當資料超過1500位元組時需要進行分片,即接下來欄位的意義;

標識:佔16位,標識其中一個分片;
標誌:佔3位,只有兩位起作用,分別表示是否可以被分片和是否是最後一個分片;
片偏移:佔13位,某片在原分組中的位置;

生存時間(TTL):佔8位,即資料報的壽命,在轉發過程中的跳數;
協議: 佔8位, 協議欄位指出此資料報攜帶的資料是使用何種協議,以便使目的主機知道把資料上交給哪個處理過程;
首部校驗和:佔16位,只檢驗資料包的首部;
源IP地址和目的IP地址:都佔32位;

在網路層和IP協議配合使用的協議ARP協議:地址解析協議,在OSI七層協議中,這個協議被認為是資料鏈路層的協議,而在TCP/IP四層協議中屬於網路層協議;

地址解析協議的作用是通過目的主機的IP地址得到目的主機的MAC地址,使得MAC幀可以順利打包;

ARP資料幀格式如下:
這裡寫圖片描述

ARP的執行過程,當A主機向B主機發送訊息的時候,A主機只知道B主機的ip地址,不知道實體地址怎麼辦? ARP有個快取記憶體,用來存放最近通訊過的目的主機的MAC和IP的對映表,先來查這張表,如果沒有,那就帶著B主機的IP地址在區域網內進行廣播,這是誰的IP地址啊? 把你的MAC地址給我回過來,此時如果區域網記憶體在這個IP地址的主機,就會迴應一個ARP響應報文,帶著自己的MAC地址,雖然ARP請求報文是廣播的,但是響應報文是單播的;

配合IP協議的還有ICMP協議,這個協議其實也是出於夾層的協議,在不同的書裡可能歸在不同層,在這裡,我們預設在網路層;

ICMP幀格式:

這裡寫圖片描述

ICMP : 網路控制報文協議;

具體細節不去學習了,只複習一下ICMP的一個實際應用例子:ping命令;

PING是應用層直接使用網路層ICMP協議的一個例子,直接跳過了傳輸層;

還有traceroute也是用了ICMP的差錯報告報文;

傳輸層:TCP和UDP

傳輸層提供了兩種截然不同風格的傳輸協議,可以根據不同的需求選擇合適的協議;

UDP:不可靠的傳輸協議,面向無連線的服務,盡最大可能的交付資料報;

UDP的報頭格式:
這裡寫圖片描述

下面是UDP的特點:

  1. udp的資料報的報頭固定長度8個位元組
  2. udp是無連線的,即傳送資料之前不需要進行連結
  3. udp使用最大努力交付,說白點就是不保證資料完整和到達
  4. udp是面向報文的,即一次交付一個完整的報文
  5. udp沒有擁塞控制,即網路擁塞也不會影響源主機的傳送效率
  6. udp支援一對多,多對多的互動式通訊

UDP的應用場景,只要面試中問到UDP那是必須問應用場景的;

既然是不可靠的傳輸,那麼對資料的完整性要求不高的場景可以使用UDP進行傳輸,例如qq語言和qq視訊的傳輸;

較短的資料報使用UDP進行傳輸,例如qq和微信的訊息傳送,這也是為什麼會在網路差的時候會出現傳送失敗和限制傳送長度的原因;

傳送的資料太長的話,在IP層會被切片,影響IP層效率,但是如果資料太短的話,IP資料報頭過大,也影響IP層效率;

TCP:可靠的,面向連線,位元組流的傳輸協議;

TCP的報頭格式:
這裡寫圖片描述

TCP報頭固定的20個位元組分別是:

源埠地址和目的埠地址:各佔32位;
序號和確認號:各佔32位,是保證可靠傳輸的基礎;
資料偏移:佔4位,指出報文段資料的起始處距離TCP報文段的起始處有多遠;
6位控制位:標誌報文屬性;
緊急指標:資料的優先,需要第一時間被交付,於是接收方就把緊急資料放在本段報文的最前方;
視窗大小:擁塞控制;

下面是TCP的特點:

  1. 每一條tcp連結只能有兩個端點,即點對點的傳輸;
  2. tcp提供可靠的交付服務,通過TCP傳輸的資料,無差錯,不丟失,不重複,並且按序到達;
  3. tcp提供全雙工通訊
  4. 面向位元組流:即交付給上層的可能不是一次完整的資料;

既然TCP提供的是可靠的傳輸,那麼可靠的傳輸到底是如何實現的,包含哪些方面?

  1. 差錯處理(超時重傳)
  2. 有序接受
  3. seq/ack確認機制
  4. 擁塞控制

除去前面給的重要的三次握手四次揮手的連結,下面重點說的TCP保證可靠性傳輸主要依賴的四種定時器和擁塞控制;

下面又是一個面試的熱點問題,第一次聽到的時候還是懵逼的,那就是如何實現一個可靠的UDP傳輸?

UDP如何實現可靠傳輸

由於在傳輸層UDP已經是不可靠的連線,那就要在應用層自己實現一些保障可靠傳輸的機制

簡單來講,要使用UDP來構建可靠的面向連線的資料傳輸,就要實現類似於TCP協議的

超時重傳(定時器)

有序接受 (新增包序號)

應答確認 (Seq/Ack應答機制)

滑動視窗流量控制等機制 (滑動視窗協議)

等於說要在傳輸層的上一層(或者直接在應用層)實現TCP協議的可靠資料傳輸機制,比如使用UDP資料包+序列號,UDP資料包+時間戳等方法。

目前已經有一些實現UDP可靠傳輸的機制,比如

UDT(UDP-based Data Transfer Protocol)
基於UDP的資料傳輸協議(UDP-based Data Transfer Protocol,簡稱UDT)是一種網際網路資料傳輸協議。UDT的主要目的是支援高速廣域網上的海量資料傳輸,而網際網路上的標準資料傳輸協議TCP在高頻寬長距離網路上效能很差。 顧名思義,UDT建於UDP之上,並引入新的擁塞控制和資料可靠性控制機制。UDT是面向連線的雙向的應用層協議。它同時支援可靠的資料流傳輸和部分可靠的資料報傳輸。 由於UDT完全在UDP上實現,它也可以應用在除了高速資料傳輸之外的其它應用領域,例如點到點技術(P2P),防火牆穿透,多媒體資料傳輸等等。

四種定時器:

TCP使用四種定時器(Timer,也稱為“計時器”):
重傳計時器:Retransmission Timer
堅持計時器:Persistent Timer
保活計時器:Keeplive Timer
時間等待計時器:Time_Wait Timer。

(1)重傳計時器:Retransmission Timer

重傳定時器:為了控制丟失的報文段或丟棄的報文段,也就是對報文段確認的等待時間。當TCP傳送報文段時,就建立這個特定報文段的重傳計時器,可能發生兩種情況:若在計時器超時之前收到對報文段的確認,則撤銷計時器;若在收到對特定報文段的確認之前計時器超時,則重傳該報文,並把計時器復位;重傳時間=2*RTT;
RTT的值應該動態計算。常用的公式是:RTT=previous RTT*i + (1-i)*current RTT。i的值通常取90%,即新的RTT是以前的RTT值的90%加上當前RTT值的10%.
Karn演算法:對重傳報文,在計算新的RTT時,不考慮重傳報文的RTT。因為無法推理出:傳送端所收到的確認是對上一次報文段的確認還是對重傳報文段的確認。乾脆不計入。

(2)堅持計時器:persistent timer

專門為對付零視窗通知而設立的。
當傳送端收到零視窗的確認時,就啟動堅持計時器,當堅持計時器截止期到時,傳送端TCP就傳送一個特殊的報文段,叫探測報文段,這個報文段只有一個位元組的資料。探測報文段有序號,但序號永遠不需要確認,甚至在計算對其他部分資料的確認時這個序號也被忽略。探測報文段提醒接收端TCP,確認已丟失,必須重傳。
堅持計時器的截止期設定為重傳時間的值,但若沒有收到從接收端來的響應,則傳送另一個探測報文段,並將堅持計時器的值加倍和並復位,傳送端繼續傳送探測報文段,將堅持計時器的值加倍和復位,知道這個值增大到閾值為止(通常為60秒)。之後,傳送端每隔60s就傳送一個報文段,直到視窗重新開啟為止;補充:
堅持定時器的原理是簡單的,當TCP伺服器收到了客戶端的0滑動視窗報文的時候,就啟動一個定時器來計時,並在定時器溢位的時候向向客戶端查詢視窗是否已經增大,如果得到非零的視窗就重新開始傳送資料,如果得到0視窗就再開一個新的定時器準備下一次查詢。通過觀察可以得知,TCP的堅持定時器使用1,2,4,8,16……64秒這樣的普通指數退避序列來作為每一次的溢位時間。

糊塗視窗綜合症

TCP的視窗協議,會引起一種通常叫做糊塗視窗綜合症的問題,具體表現為,當客戶端通告一個小的非零視窗時,伺服器立刻傳送小資料給客戶端並充滿其緩衝區,一來二去就會讓網路中充滿小TCP資料報,從而影響網路利用率。對於傳送方和接收端的這種糊塗行為。

再次補充:

TCP通過讓接收方指明希望從傳送方接收的資料位元組數(即視窗大小)來進行流量控制。如果視窗大小為 0會發生什麼情況呢?這將有效地阻止傳送方傳送資料,直到視窗變為非0為止。
TCP不對ACK報文段進行確認, TCP只確認那些包含有資料的ACK報文段。
如果一個確認丟失了(這個確認是”接收方“向”傳送方“傳送的ACK,通知”傳送方“自己的視窗已經非0了),則雙方就有可能因為等待對方而使連線終止:接收方等待接收資料(因為它已經向傳送方通告了一個非 0的視窗),而傳送方在等待允許它繼續傳送資料的視窗更新。為防止這種死鎖情況的發生,傳送方使用一個堅持定時器 (persist timer)來週期性地向接收方查詢,以便發現視窗是否已增大。這些從傳送方發出的報文段稱為視窗探查 (window probe)。

(3)保活計時器:keeplive timer

每當伺服器收到客戶的資訊,就將keeplive timer復位,超時通常設定2小時,若伺服器超過2小時還沒有收到來自客戶的資訊,就傳送探測報文段,若傳送了10個探測報文段(沒75秒傳送一個)還沒收到響應,則終止連線。

補充:

保活定時器更加的簡單,還記得FTP或者Http伺服器都有Sesstion Time機制麼?因為TCP是面向連線的,所以就會出現只連線不傳送資料的“半開放連線”,伺服器當然要檢測到這種連線並且在某些情況下釋放這種連線,這就是保活定時器的作用。其時限根據伺服器的實現不同而不通。另外要提到的是,當其中一端如果崩潰並重新啟動的情況下,如果收到該端“前生”的保活探察,則要傳送一個RST資料報文幫助另一端結束連線。

(4)時間等待計時器:Time_Wait Timer

在連線終止期使用,當TCP關閉連線時,並不認為這個連線就真正關閉了,在時間等待期間,連線還處於一種中間過度狀態。這樣就可以時重複的fin報文段在到達終點後被丟棄,這個計時器的值通常設定為一格報文段壽命期望值的兩倍。

補充:

2MSL定時器:MSL是報文段做大生存時間(Maximum Segment Lifetime),設定這個定時器有兩個目的:
其一是為了測量連線處於TIME_WAIT狀態的時間.這樣可以讓TCP再次傳送最後的ACK以防止這個ACK丟失(如果丟失,另一端會重傳FIN)。
其二,為允許老的重複分節在網路中消逝。具體可以解釋為,如果一個TCP連線在斷開之前有迷途分節尚未消逝,在斷開該TCP連線之後立刻重啟一個同樣的連線(雙方的IP地址和埠port相同),這時之前的迷途的老分節可能對新的新的TCP連線接收,從而造成未定義的錯誤。為了避免這種情況,TCP規定在TIME_WAIT狀態,不能啟動一個連線的化身。既然TIME_WAIT狀態維持2MSL,這就保證了一個連線上的分組及其應該在 2MSL內都會消失。

TCP的擁塞控制

就和告訴公路一樣,車多了會堵車,資料多了,網路也會堵車,甚至還會丟車;

那麼TCP為了在堵車的情況下依然保證可靠性傳輸必然要做一些措施,不然在網路堵車的情況下依然快速發資料的話只會雪上加霜,下面就複習一下幾種擁塞控制的方法:

  1. 慢開始
  2. 擁塞避免
  3. 快重傳
  4. 快恢復

與其說這是四種方法,我覺得更好的理解這是四種狀態,四個階段;

慢開始和擁塞避免

傳送方維護一個擁塞視窗,不同於傳送視窗,擁塞窗用於擁塞控制,但是傳送視窗一般等於擁塞視窗,有時接收方的接受能力太小,傳送視窗還會小於擁塞視窗;

如何確定網路發生擁塞?

如果頻繁的出現重傳和丟包的現象,那麼就有可能網路擁塞,但是剛開始的時候並沒有傳送資料,該如何確定傳送資料的位元組大小呢?

慢開始,由小到大增加發送視窗大小,也就是擁塞視窗的值,其實這裡的慢也不是很慢,因為是以2的指數的形式增長的;假設我們以報文段為單位,剛開始擁塞視窗的值 cwnd = 1, 傳送報文w1,收到w1的確認後,cwnd增加一,此時可以傳送2個報文段,當收到這兩個報文段的確認後,cwnd增長到4,就以2的指數開始增長;

但是總不能讓擁塞視窗這麼一直增長下去,這時候就有一個叫做慢開始門限的值 ssthresh ,當cwnd < ssthresh 時使用慢開始演算法,當cwnd > ssthresh時停止使用慢開始演算法,改為擁塞避免演算法,當cwnd == ssthresh時二選一;

那麼此時肯定都很好奇這個門限值到底是如何規定的?

一般慢開始的門限值設為16個報文段的大小(一個MSS == 1460位元組);

當cwnd的大小達到門限值後,就要進入擁塞避免階段了,那麼擁塞避免到底是如何處理的?

擁塞避免是使擁塞視窗呈線性增長,即從原先的乘法增大變為現在的加法增大,即每經過一個往返時間,cwnd的值增加1;

值得一提的是,一旦檢測到網路擁塞,此時會將門限值更新為傳送視窗的一般,然後cwnd的值重新置為1,重新開始慢開始演算法;

快重傳和快恢復

快重傳的實現是這樣的,當接收方收到一個失序的報文段,立馬傳送一個重複的確認報文,而不是等傳送資料時捎帶,這樣可以儘快的讓傳送方知道,當傳送方連續收到三個重複的確認報文,不論重傳計時器是否到時間,立馬重傳丟失的報文段;

快恢復是配合快重傳的演算法,既然連續收到三個重複的確認,不難判斷此時網路出現了擁塞,那麼此時不但要快重傳還要想辦法減緩網路壓力,此時快恢復演算法就來了;

快恢復:當傳送方連續收到三個重複的確認時,就進入擁塞避免階段,並且把門限值減半;

至於應用層的協議就特別多了,下一篇部落格將解析我自己寫的一個web伺服器,基於http協議的,來進行應用層和網路程式設計的學習;