【網絡通信 -- 直播】IM 學習系列 -- 網絡通信協議簡介(HTTP 協議 三)

【網絡通信 -- 直播】IM 學習系列 -- 網絡通信協議簡介(HTTP 協議 三)

【1】HTTP 的實體數據

【1.1】數據類型與編碼

MIME,多用途互聯網郵件擴展(Multipurpose Internet Mail Extensions), MIME 把數據分成了八大類,每個大類下再細分出多個子類,形式是“type/subtype”的字符串;
HTTP 中常用的類別:
text,即文本格式的可讀數據,如 超文本文檔 text/html、純文本 text/plain、樣式表 text/css 等;
image,即圖像文件,如 image/gif、image/jpeg、image/png 等;
audio/video,音頻和視頻數據,例如 audio/mpeg、video/mp4 等;
application,數據格式不固定,可能是文本也可能是二進制,必須由上層應用程序來解釋;如 application/json、application/javascript、application/pdf 等; application/octet-stream,即不透明的二進制數據,表示無法確定數據類型;

Encoding type(編碼格式) 常用類型
gzip,GNU zip 壓縮格式,deflate,zlib(deflate)壓縮格式;br,專門爲 HTTP 優化的新壓縮算法(Brotli)

【1.2】數據類型使用的頭字段

HTTP 協議爲此定義了兩個 Accept 請求頭字段和兩個 Content 實體頭字段,用於客戶端和服務器進行“內容協商”,客戶端用 Accept 頭告訴服務器希望接收什麼樣的數據,服務器用 Content 頭告訴客戶端實際發送了什麼樣的數據;

Accept 字段標記的是客戶端可理解的 MIME type,可以用“,”做分隔符列出多個類型
Accept: text/html,application/xml,image/webp,image/png

Content-Type 告訴實體數據的真實類型
Content-Type: text/html
Content-Type: image/png

Accept-Encoding 字段標記的是客戶端支持的壓縮格式可以用“,”列出多個,服務器可以選擇其中一種來壓縮數據;
Content-Encoding 實際使用的壓縮格式;
Accept-Encoding: gzip, deflate, br
Content-Encoding: gzip

【1.3】語言類型

語言類型即自然語言,例如英語、漢語、日語等,用“type-subtype”的形式標記語言與下屬的地區性方言

語言類型使用的頭字段
Accept-Language 字段標記了客戶端可理解的自然語言,也允許用“,”做分隔符列出多個類型
Accept-Language: zh-CN, zh, en

Content-Language 告訴客戶端實體數據使用的實際語言類型
Content-Language: zh-CN

請求頭字段是 Accept-Charset表示字符集,Content-Type 字段的數據類型後面用“charset=xxx”來表示字符集
Accept-Charset: gbk, utf-8
Content-Type: text/html; charset=utf-8

【1.4】內容協商的質量值
HTTP 協議裏用 Accept、Accept-Encoding、Accept-Language 等請求頭字段進行內容協商的時候,可以用一種特殊的“q”參數表示權重來設定優先級,權重的最大值是 1,最小值是 0.01,默認值是 1,如果值是 0 就表示拒絕;具體的形式是在數據類型或語言代碼後面加一個“;”,然後是“q=value”,在 HTTP 的內容協商裏“;”的意義是小於“,”的;

Accept: text/html,application/xml;q=0.9,*/*;q=0.8
表示瀏覽器最希望使用的是 HTML 文件,權重是 1,其次是 XML 文件,權重是 0.9,最後是任意數據類型,權重是 0.8;
服務器收到請求頭後,就會計算權重,再根據自己的實際情況優先輸出 HTML 或者 XML;

【2】HTTP 傳輸大文件的方法

【2.1】數據壓縮

缺點 : gzip 等壓縮算法通常只對文本文件有較好的壓縮率,而圖片、音頻視頻等多媒體數據本身就已經是高度壓縮的,再用 gzip 處理也不會變小(甚至還有可能會增大一點);

【2.2】分塊傳輸

分塊傳輸在 HTTP 協議裏就是“chunked”分塊傳輸編碼,在響應報文裏用頭字段“Transfer-Encoding: chunked”來表示,意思是報文裏的 body 部分不是一次性發過來的,而是分成了許多的塊(chunk)逐個發送
“Transfer-Encoding: chunked”和“Content-Length”這兩個字段是互斥的,即響應報文裏這兩個字段不能同時出現,一個響應報文的傳輸要麼是長度已知,要麼是長度未知(chunked)

分塊傳輸的編碼規則類似於響應頭採用了明文的方式,
1. 每個分塊包含兩個部分,長度頭和數據塊;
2. 長度頭是以 CRLF(回車換行,即\r\n)結尾的一行明文,用 16 進制數字表示長度;
3. 數據塊緊跟在長度頭後,最後也用 CRLF 結尾,但數據不包含 CRLF;
4. 最後用一個長度爲 0 的塊表示結束,即“0\r\n\r\n”;

【2.3】範圍請求

“範圍請求”(range requests)允許客戶端在請求頭裏使用專用字段來表示只獲取文件的一部分,相當於是客戶端的“化整爲零”,
範圍請求不是 Web 服務器必備的功能,服務器若支持範圍請求則在響應頭裏使用字段“Accept-Ranges: bytes”告知客戶端支;若服務器不支持範圍請求則發送“Accept-Ranges: none”,或者乾脆不發送“Accept-Ranges”字段;


請求頭 Range 是 HTTP 範圍請求的專用字段,格式是“bytes=x-y”,其中的 x 和 y 是以字節爲單位的數據範圍,要注意 x、y 表示的是“偏移量”,範圍必須從 0 計數,例如前 10 個字節表示爲“0-9”,第二個 10 字節表示爲“10-19”,而“0-10”實際上是前 11 個字節;range 的格式也很靈活,起點 x 和終點 y 可以省略,能夠很方便地表示正數或者倒數的範圍;
假設文件是 100 個字節則:“0-”表示從文檔起點到文檔終點,相當於“0-99”,即整個文件;“10-”是從第 10 個字節開始到文檔末尾,相當於“10-99”;“-1”是文檔的最後一個字節,相當於“99-99”;“-10”是從文檔末尾倒數 10 個字節,相當於“90-99”;

服務器收到 Range 字段後,需要做四件事;
第一,必須檢查範圍是否合法,比如文件只有 100 個字節,但請求“200-300”,這就是範圍越界了,服務器就會返回狀態碼 416,意思是“範圍請求有誤,無法處理”;
第二,如果範圍正確,服務器就可以根據 Range 頭計算偏移量,讀取文件的片段了,返回狀態碼 “206 Partial Content” 和 200 的意思差不多,但表示 body 只是原數據的一部分;
第三,服務器要添加一個響應頭字段 Content-Range,告訴片段的實際偏移量和資源的總大小,格式是“bytes x-y/length”,與 Range 頭區別在沒有“=”,範圍後多了總長度,例如,對於“0-10”的範圍請求,值就是“bytes 0-10/100”;
第四,發送數據,直接把片段用 TCP 發給客戶端,一個範圍請求便處理完了;

多段下載、斷點續傳也是基於範圍請求實現的,要點是:
1. 先發個 HEAD,看服務器是否支持範圍請求,同時獲取文件的大小;
2. 開 N 個線程,每個線程使用 Range 字段劃分出各自負責下載的片段,發請求傳輸數據;
3. 下載意外中斷也不怕,不必重頭再來一遍,只要根據上次的下載記錄,用 Range 請求剩下的部分;

【2.4】多段數據

這種情況需要使用一種特殊的 MIME 類型:“multipart/byteranges”,表示報文的 body 是由多段字節序列組成的,並且還要用一個參數“boundary=xxx”給出段之間的分隔標記;

每一個分段必須以“- -boundary”開始(前面加兩個“-”),之後要用“Content-Type”和“Content-Range”標記這段數據的類型和所在範圍,然後就像普通的響應頭一樣以回車換行結束,再加上分段數據,最後用一個“- -boundary- -”(前後各有兩個“-”)表示所有的分段結束;

問題舉例

【1】假設你要使用 POST 方法向服務器提交一些 JSON 格式的數據,裏面包含有中文,請求頭應該是什麼樣子的呢

POST /serv/v1/user/auth HTTP/1.1
Content-Type: application/json; charset=gbk, utf-8
Content-Language: zh-CN, zh

【2】如果對一個被 gzip 的文件執行範圍請求,比如“Range: bytes=10-19”,那麼這個範圍是應用於原文件還是壓縮後的文件呢

range 是針對原文件的;

參考致謝
本博客爲博主的學習實踐總結,並參考了衆多博主的博文,在此表示感謝,博主若有不足之處,請批評指正。

【1】透視HTTP協議

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章