網絡、HTTP相關學習總結

圖解HTTP目錄

引言:上圖是《圖解 HTTP》這本書的目錄,最近又從新讀了一下這本書,而後打算寫篇總結,來加深本身的理解,然而在作總結的時候以爲仍是全面總結下網絡相關的知識吧,因此又在網上找了大量的資料,最終完成了本文。html

鄭重聲明:本文只是個人學習總結,不敢誤人子弟,若是你看到了這篇文章,以爲有什麼錯誤的地方還請指出。本文參考了大量的博客、文章等,若有侵權,請與我聯繫。謝謝android

OSI vs TCP/IP

OSI

OSI全稱爲開放式系統互聯通信參考模型(Open System Interconnection Reference Model)。OSI 將計算機網絡體系結構劃分爲 7 層。git

  1. 物理層:在局部局域網上傳送數據楨,它負責管理計算機管理通信設備和網絡媒體之間的互通。包括了針腳、電壓、線纜電壓、集線器、中繼器、網卡、主機接口等。
  2. 數據鏈路層:負責網絡尋址、錯誤偵測和改錯。當表頭和表尾被加之數據包時會造成楨。數據鏈表頭(DLH)是包含了物理地址和錯誤偵測和改錯的方法。數據鏈表尾(DLT)是一串指示數據包末端的字符串。例如以太網、無線局域網(Wi-Fi)和通用分組無線服務(GPRS)。
  3. 網絡層:決定數據的路徑選擇和轉寄,將網絡表頭(NH)加至數據包,以造成分組。網絡表頭包含了網絡數據,例如:互聯網協議(IP)等。
  4. 傳輸層:把傳輸表頭(TH)加至數據以造成數據包。傳輸表頭包含了所使用的協議等發送信息,例如:傳輸控制協議(TCP)等。
  5. 會話層:負責在數據傳輸中設置和維護計算機網絡中兩臺計算機之間的通信鏈接。
  6. 表示層:將數據轉化爲能與接收者的系統格式兼容並適合傳輸的格式。
  7. 應用層:提供爲應用軟件而設的接口,以設置與另外一軟件之間的通訊。例如:HTTP、HTTPS、FTP、TELNET、POP三、SMTP、SSH等。

OSI 模型是一個標準而非實現,TCP/IP 四層模型由 OSI 7 層模型簡化而來,是一個應用的具體實現。github

下面具體說下四層模型,從下往上提及:web

TCP/IP

鏈路層

又名數據鏈路層,網絡接口層。用來處理網絡鏈接的硬件部分。算法

  • 以太網協議

以太網(Ethernet)規定,一組電信號構成一個數據包,叫作幀(Frame)。每一幀分紅兩部分:標頭和數據。標頭的長度固定爲14字節,數據的長度範圍爲46~1500字節,若是數據不夠長,則須要填充(好比ARP、RARP),若是過長,就必須分割成多個幀進行傳輸。緩存

以太網幀格式

標頭固定的14字節爲:目的地址(6個字節)、源地址(6個字節)和類型(2個字節)。目的地址/源地址爲MAC地址,類型:0x0800 是IP數據報,0x0806 是ARP請求,0x8035 是 RARP。末尾的CRC是校驗碼。bash

以太網是採用廣播的形式發送數據包的。好比,一個子網絡中有3臺計算機,1號計算機想給2號計算機發送一個數據包,2號、3號計算機都會收到這個包,而後讀取這個包的標頭,獲取目的MAC地址,和自身的MAC地址作匹配,若是相同則接收這個包,不然就丟棄這個包。服務器

從上述廣播能夠看出,以太網數據包必須知道對方的MAC地址才能夠傳輸數據,那麼一個網卡是如何知道另外一個網卡的MAC地址的呢?其實就是經過ARP協議得到的,後續文中將會說明。網絡

網絡層

又名網絡互聯層。用來處理在網絡上流動的數據包。

IP協議

互聯網是無數子網絡共同組成的一個巨型網絡。同一個子網絡之間傳輸數據用MAC地址經過廣播的方式傳輸,那麼不一樣子網絡之間呢?

網絡層的誕生就是要引進一套新的地址,使得咱們可以區分不一樣的計算機是否數據同一個子網絡。

規定網絡地址的協議,叫作IP協議,它所定義的地址稱爲IP地址。目前普遍採用的是IP協議第四版,簡稱IPv4。這個版本規定,網絡地址由32個二進制位組成。習慣上,咱們分紅四段的十進制數表示IP地址,從0.0.0.0到255.255.255.255。

IP地址分爲兩個部分,前一部分表明網絡,後一部分表明主機。可是單從IP地址咱們沒法判斷網絡部分究竟是前24位仍是前16位等等,這時候就須要用到子網掩碼(subnet mask)了。所謂子網掩碼就是表示子網絡特徵的一個參數。它在形式上等同與IP地址,也是一個32位二進制數,它的網絡部分所有爲1,主機部分所有爲0。好比,IP地址爲192.168.1.1,若是已知網絡部分是前24位,主機部分是後8位,那麼子網掩碼就是11111111.11111111.11111111.00000000,對應十進制就是255.255.255.0。將兩個IP地址分別和子網掩碼進行AND運算,而後比較結果是否相同,就能夠判斷兩個IP是否屬於一個子網絡了。

IP數據報格式

IP數據報格式

IP數據報的首部長度和數據長度都是可變長的,但老是4字節的整數倍。對於IPv4,4位版本字段是4。4位首部長度是以4字節爲單位的,最小值是5,也就是說首部長度最小是4*5=20字節,也就是不帶任何選項的IP首部,4位能表示的最大值是15,也就是說首部長度最大是60字節。

8位TOS字段有3個位用來指定IP數據報的優先級(目前已經廢棄不用),還有4個位表示可選的服務類型(最小延遲、最大吞吐量、最小成本),還有一個位老是0。16位總長度是整個數據報(包括IP首部和IP層payload)的字節數,最大是65535字節,上面提到過以太網數據幀的數據部分最大爲1500字節,所以,若是IP數據包超過了1500字節,就須要分割成幾個以太網數據幀進行傳輸。

每傳一個IP數據報,16位的標示增長1,可用於分片和從新組裝數據報。3位標誌和13位片偏移用於分片。

TTL(time to live)是這樣用的:源主機爲數據包設定一個生存時間,好比64,每過一個路由器就把該值減1,若是減到0就表示路由已經太長了仍然找不到目的主機的網絡,就丟棄該包,所以這個生存時間的單位不是秒,而是跳(hop)。協議字段指示上層協議是TCP、UDP、ICMP仍是IGMP。而後是校驗和,只校驗IP首部,數據的校驗由更高層協議負責。接下來是32位的IP地址。

ARP協議

看到這裏,就知道了要想往對方機器傳輸數據須要IP地址和MAC地址,IP地址能夠經過DNS服務得到,而MAC地址怎麼獲取呢?

這裏須要分兩種狀況:

第一種狀況,若是兩臺主機不在同一個子網絡,實際上是沒有辦法獲得對方的MAC地址的,只能把數據包傳送到兩個子網絡接處的網關(getaway),讓網關去處理。

第二種狀況,若是兩臺主機在同一個子網絡,那麼咱們能夠經過ARP協議,獲得對方的MAC地址。簡單來講就是在以太網首部目的MAC地址裏面填寫FF:FF:FF:FF:FF:FF,表示這是一個廣播地址。收到這個廣播的主機就會去匹配本身的IP地址,若是匹配則回覆本身的MAC地址,不然丟棄這個包。

傳輸層

對應用層提供處於網絡鏈接中兩臺計算機的數據傳輸。網絡層是主機到主機之間的通訊,而傳輸層是創建端口到端口的通訊。表明:UDP、TCP。

UDP

UDP段格式

UDP 首部比較簡單,總共8字節。具體見上圖。

TCP

TCP段格式

和UDP協議同樣也有源端口號和目的端口號,通信的雙方由IP地址和端口號標示。32位序號、32位確認號、窗口大小稍後詳細解釋。4位首部長度和IP協議頭相似,標示TCP協議頭的長度,若是沒有選項字段,TCP協議頭最短爲20字節。URG、ACK、PSH、RST、SYN、FIN是六個控制位,稍後將解釋SYN、ACK、FIN、RST,其它從略。

看一個簡單的一問一答的例子:

TCP鏈接創建斷開

三次握手

  1. 客戶端發出段1(Client:SYN_SEND),標誌位是SYN,序號是1000,這個序號在網絡通信中用做臨時的地址,每發送一個數據字節,這個序號要加1,這樣在接收端能夠根據序號排出數據包的正確順序,也能夠發現丟包的狀況,另外,規定SYN位和FIN位也要佔一個序號,此次雖然沒有發數據,可是因爲發送了SYN位,所以下次再發送應該用序號1001。mss表示最大段尺寸,若是一個段太大,封裝成幀後超過了鏈路層的最大幀長度,就必須在IP層分片,爲了不這種狀況,客戶端生命本身的最大段尺寸,建議服務器端發來的段不要超過這個長度。

  2. 服務器發出段2(Server:SYN_RECV),也帶有SYN位,同時置ACK位表示確認,確認序號是1001,表示「我接收到序號1000及其之前全部的段,請你下次發送序號位1001的段」,也就是應答了客戶端的鏈接請求,同時也給客戶端發出一個鏈接請求,同時聲明最大尺寸爲1024。

  3. 客戶端發出段3(ESTABLISHED),對服務器的鏈接請求進行應答,確認序號是8001。

在TCP通信中,若是一方接收到另外一方發來的段,讀出其中的目的端口號,發現本機並無任何進程使用這個端口,就會應答一個包含RST位的段給另外一方。

數據傳輸

  1. 客戶端發出段4,包含從序號1001開始的20個字節數據。
  2. 服務器發出段5,確認序號爲1021,對序號1001-1020的數據表示確認收到,同時請求發送序號1021開始的數據,服務器在應答的同時也向客戶端發送從序號8001開始的10個字節數據,這稱之爲piggyback。
  3. 客戶端發出段6,對服務器發來的序號8001-8010的數據表示確認收到,請求發送序號8001開始的數據。

在數據傳輸過程當中,ACK和確認序號是很是重要的,應用層交給TCP協議發送的數據會暫存在TCP層的發送緩衝區中,發出數據以後,只有收到了對方的應答ACK段,才確認數據是成功發送了,並從緩存區中移除。若是等待超時,會進行重發。

四次揮手

  1. 客戶端發出段7(Client:FIN_WAIT_1),FIN位表示關閉鏈接的請求。
  2. 服務器發出段8(Server:COSE_WAIT, Client:FIN_WAIT_2),應答客戶端的關閉鏈接請求。
  3. 服務器發出段9(Server:LAST_ACK),其中也包含FIN位,向客戶端發送關閉鏈接的請求。
  4. 客戶端發出段10(Client:TIME_WAIT)應答服務器的關閉鏈接請求。

創建鏈接是三次握手,而關閉一般鏈接須要四段(也有三次的狀況),服務器的應答和關閉鏈接請求一般不合並在一個段中,由於有鏈接半關閉的狀況,這種狀況下客戶端關閉鏈接以後就不能再發送數據給服務器了,可是服務器還能夠發送數據給客戶端,直到服務器也關閉鏈接爲止。

客戶端發出段10以後,不是立馬關閉鏈接,而是進入TIME_WAIT狀態,等待2MSL。MSL是Maximum Segment Lifetime的縮寫,表示報文最大生存時間,當段10因爲網絡緣由沒有成功發送時,通過1MSL服務器會重發段9,段9傳輸最慢須要1MSL,因此須要等待2MSL來確保最後一次ACK成功發送。

滑動窗口

咱們知道UDP協議是不可靠的,當發送端發送的速度過快,接收端收到數據後處理的速度較慢,而緩衝區大小是固定的,就會丟失數據。TCP協議經過滑動窗口(Sliding Window)機制解決這一問題。

滑動窗口

  1. 發送端發起鏈接,聲明最大尺寸是1460,初始序號是0,窗口大小是4K,表示「個人接收緩衝區還有4K字節空閒,你發的數據不要超過4K」。接收端應答鏈接請求,聲明最大段尺寸是1024,初始序號是8000,窗口大小是6K。發送端應答,三次握手結束。

  2. 發送端發出段4-9,每一個段帶1K的數據,發送端根據窗口大小知道接收端的緩衝區滿了,所以中止發送數據。

  3. 接收端的應用程序提走2K數據,接收緩衝區又有了2K的空閒,接收端發送段10,在應答已收到6K數據的同時聲明窗口大小爲2K。

  4. 接收端的應用程序又提走2K數據,接收緩衝區有4K空閒,接收端發出段11,從新聲明窗口大小爲4K。

  5. 發送端發出段12-13,每一個段帶2K的數據,段13同時還包含FIN位。

  6. 接收端應答接收到的2K數據(6145-8192),再加上FIN位佔一個序號8193,所以應答序號是8194,鏈接處於半關閉狀態,接收端同時聲明窗口大小爲2K。

  7. 接收端的應用程序提走2K數據,接收端從新聲明窗口大小爲4K。

  8. 接收端的應用程序提走剩下的2K數據,接收緩衝區全空,接收端從新聲明窗口大小爲6K。

  9. 接收端的應用程序在提走所有數據後,決定關閉鏈接,發出段17包含FIN位,發送端應答,鏈接徹底關閉。

應用層

就是平時接觸最多的一層,好比HTTP、DNS、FTP。

以 HTTP 爲例,爲了傳輸方便在傳輸層(TCP協議)把從應用層收到的數據(HTTP報文)進行分割,並在各個報文上打上標記序號及端口號後轉發給網絡層。

在網絡層(IP協議),增長做爲通信目的地的 MAC 地址後轉發給鏈路層。

接收端的服務器在鏈路層收到數據,按序往上層發送,一直到應用層。

HTTP傳輸示例

HTTP 狀態碼

下面👇的表格列出了常見的 HTTP 狀態碼

HTTP狀態碼30二、303和307的故事

HTTP/2

HTTP/2,簡稱h2(基於TLS/1.2或以上版本的加密鏈接)或h2c(非加密鏈接),是 HTTP 協議的第二個主要版本,主要基於 SPDY 協議。

SPDY 由 Google 研發,基於傳輸控制協議(TCP)的應用層協議,其主要設計目的是下降網頁加載時間。經過優先級和多路複用,SPDY 使得只須要建立一個 TCP 鏈接便可傳送網絡內容和圖片資源。SPDY 中普遍應用了 TLS 加密,傳輸內容也均以 gzip 或者 DEFLATE 格式壓縮,另外 SPDY 還支持服務端主動推送數據到客戶端。

HTTP/2 和 SPDY 的不一樣點

  1. HTTP/2 支持明文傳輸,而 SPDY 強制使用 TLS 加密。
  2. HTTP/2 頭壓縮使用的算法是 HPACK,而 SPDY 使用的是 DEFLATE

HTTP/2 的優勢

1. 幀、消息和流

HTTP/2 採用了二進制而非文原本進行傳輸數據,這也是和 HTTP/1.x 的最大區別。HTTP/2 將一個 TCP 鏈接分爲若干個流(Stream),每個流中能夠傳輸若干個消息(Message),每個消息由若干個最小的二進制幀(Frame)組成。

流(Stream)

如上圖所示,流通常表示的是每一個請求和響應,在 HTTP/2 中能夠多個流同時傳輸。

消息(Message)

消息是一組幀,表示某一個具體的請求或者響應。

幀(Frame)

幀是 HTTP/2 數據傳輸中的最小單位。每一幀都包含標頭和數據,頭部(固定9個字節)整個幀格式以下:

+-----------------------------------------------+
    |                 Length (24)                   |
    +---------------+---------------+---------------+
    |   Type (8)    |   Flags (8)   |
    +-+-------------+---------------+-------------------------------+
    |R|                 Stream Identifier (31)                      |
    +=+=============================================================+
    |                   Frame Payload (0...)                      ...
    +---------------------------------------------------------------+
複製代碼
  • length 佔3個字節表示的是整個幀的大小。

  • type 表示類型,目前規定了10種類型,具體以下:

    • 0x0:DATA 數據幀類型
    • 0x1:HEADERS 請求頭類型
    • 0x2:PRIORITY 設置流的優先級
    • 0x3:RST_STREAM 終止流
    • 0x4:SETTINGS 設置此鏈接的參數
    • 0x5:PUSH_PROMISE 服務器推送
    • 0x6:PING 測試 RTT
    • 0x7:GOAWAY 終止鏈接
    • 0x8:WINDOW_UPDATE 流量控制
    • 0x9:CONTINUATION 繼續傳輸頭部數據
  • flag 是標誌位,常見的有 END_STREAM 、 END_HEADERS 和 PADDED。詳細參加這裏

  • R 是保留位

  • identifier 標示符,用於跟蹤邏輯流的幀成員關係。簡單的說就是標示的哪一個流。

2.多路複用

知道了上述流的概念以後,多路複用就好理解了。HTTP/1.0 每次都須要通過三次握手才能夠傳輸數據,HTTP/1.1 中雖然增長了keep-alive能夠不用每次創建鏈接,可是仍是須要等待上一個響應返回以後,才能夠發送新的請求,而在 HTTP/2.0 中只增長請求只須要增長一個流便可,數據流以消息的形式發送,而消息又由一個或多個幀組成,多個幀之間能夠亂序發送。

3.優先級排序

因爲能夠進行多路複用,服務器和客戶端的幀都是交錯發送的,對於發送給服務器的幀,爲了解決處理的前後問題,所以引入了數據流的優先級。經過優先級類型(PRIORITY)的幀或者標頭幀能夠給流設置優先級。也能夠定義依賴關係,容許在一個資源以前加載另外一個資源。還能夠將優先級組合到一個依賴樹中,讓開發者控制每一個流的重要性。

優先級依賴樹

在上圖👆中,字母標示流標示符,數字表示分配給每一個流的權重。樹的根是流 A,首先會向它分配資源,而後才向依賴它的流 B 和 C 分配資源。爲流 B 分配了 40% 的權重,流 C 分配了 60% 的權重,即流 B 和 C 分別佔用 40% 和 60% 的可用資源。依次往下。

4.頭壓縮

專門爲 HTTP/2 定製的 HPACK 算法爲頭壓縮提供了很好的支持。它使用了一份 索引表 來定義經常使用的 HTTP Header,把經常使用的 HTTP Header 存放在表裏,請求的時候只須要發送對應的索引便可,舉個🌰 :method=GET 對應索引值爲2,path=/index.html 索引值爲5。那麼只須要給服務端發送一個 Frame,該 Frame 的 payload 是 0x8285,Frame 的 type 設置爲 HEADERS 類型,即可以知道這是一個請求頭,內容是 GET /index.html。既節儉了流量,又提升了傳輸效率。

0x8285 而不是 0x0205?這是由於高位設置爲1表示這個字節是一個徹底索引值(key 和 value 都在索引中)。相似的,經過高位的標誌位能夠區分出這個字節是屬於一個徹底索引值,仍是僅索引了key,仍是 key 和 value 都沒有索引。(具體能夠看下這篇文章(1.3 首部字段及首部塊的表示))由於索引表的大小是有限的,它僅保存了一些經常使用的 HTTP Header,同時每次請求還能夠在表尾動態追加新的 HTTP Header 緩存。動態部分稱之爲 Dynamic Table。Static Table 和 Dynamic Table 在一塊兒組成了索引表。

<----------  Index Address Space ---------->
<-- Static  Table -->  <-- Dynamic Table -->
+---+-----------+---+  +---+-----------+---+
| 1 |    ...    | s |  |s+1|    ...    |s+k|
+---+-----------+---+  +---+-----------+---+
                       ^                   |
                       |                   V
                 Insertion Point      Dropping Point
複製代碼

HPACK 不只經過索引值來下降數據量,同時還會將字符串進行 霍夫曼編碼 來壓縮字符串的大小。

5.服務端推送

做爲 HTTP/2 的一個重磅功能,也不是服務器想推就能夠推的,服務器要遵循請求-響應這個模型,只不過服務器對同一個請求能夠推送多個響應。客戶端在交換 SETTINGS Frame 時,設置字段 SETTINGS_ENABLE_PUSH (0x2) 爲1顯示容許服務器推送。

當服務端須要主動推送某個資源時,便會發送一個 Frame type 爲 PUSH_PROMISE 的 Frame,裏面帶了 PUSH 須要新建的 Stream ID。意思時告訴客戶端「接下來我要用這個ID向你發送東西,你準好接着」。

參考:

圖解 HTTP

OSI模型

HTTP/2

TCP/IP協議基礎

SPDY

HTTP/2 幕後原理

HTTP/2 新特性淺析

相關文章
相關標籤/搜索