Ⅰ-Introduce
- 先來講講這篇文章的誘因,一個安卓開發朋友去面試,有了下面的對話:
- 面試官:"一個界面有十個請求,那么十個請求建立了幾次連接?"
- 朋友:"巴拉巴拉......"
- 面試官:"切!只有一個,菜!"
- 朋友:"嗯...",此時內心OS:"TM為啥只有一個,我不服,這擺明為難我!!!"
-
(一場面試愉快的結束了...)
os like this.JPG
- 個人認為:不講場景,不基于協議討論這個問題就是耍流氓,擺明不想真招人!!!
- 我聽到了這個問題后就想自己在學習了解下為什么只有一次,當然我內心是想證明面試官是錯的
- 分析一波文章寫的時候的心路歷程 : TCP > HTTP 1.0 & HTTP 1.1 > HTTP 2.0 > 得出結論
- 結論在最后,也可以直接看結論!!!!
- 如果我理解的哪里有錯誤,請一定告訴我,阿里嘎多~
Ⅱ-TCP協議
1 簡介
-
各個協議的作用和關系
- 以太網(Ethernet)協議:解決局域網內點對點通信
- IP協議: 解決多個局域網之間的通信
- TCP協議: TCP 是以太網協議和IP協議的上層協議,也是應用層協議的下層協議
- TCP 協議: 保證數據通信的完整性和可靠性,防止丟包。IP協議只是一個地址協議,并不保證數據包的完整。如果路由器丟包(比如緩存滿了,新進來的數據包就會丟失),就需要發現丟了哪一個包,以及如何重新發送這個包.這就要依靠TCP協議。
2 數據包
-
TCP數據包
- 以太網數據包(packet)的大小是固定的,從1518字節,增加到1522字節。22字節是以太網頭信息(head),其中1500 字節是負載(payload).
- IP數據包在以太網數據包的payload中,他也有自己的頭信息,也是20字節,所以IP數據包的負載為1480字節
- TCP數據包又在IP數據包的payload中,20字節的頭信息,實際負載只有1460字節,另外IP&TCP協議往往有額外的頭信息,所以TCP負載實際為1400字節左右。
所以一個packet頭信息就要占100多字節,如果是條1500字節的信息,那就不得不分成兩個packet,所以壓縮頭信息,提高傳輸速度成為HTTP/2協議的重點需要改進的點
-
TCP數據包編號:SEQ
- 一個超過1400字節的數據,必須拆成多個包進行傳輸數據,那么就需要把拆開的數據包再組合起來,那么數據包編號(SEQ)也就有作用了,既能將傳輸的數據按照一定的順序組裝起來,又能確定丟包丟的是哪個包
- 規則:
* 第一個包的編號是隨機的,假設是0號包,第一個包內存儲的字節是100字節
* 那么第二個包的編號就是100
* 也可以由第二個包的編號和第一個包的編號確定第一個包內包含的數據負載是多少
-
數據包組裝
- 數據包的組裝不由應用程序完成,有操作系統完成,操作系統將數據包組裝好再給應用程序使用,TCP數據包里有個port參數,數據包完成組裝,操作系統根據端口信息,將packet轉交給監聽特定端口號的應用程序
- 應用程序收到組裝好的原始數據,以瀏覽器為例,就會根據 HTTP 協議的Content-Length字段正確讀出一段段的數據。這也意味著,一次 TCP通信可以包括多個HTTP通信
3 數據傳輸和丟包處理
- 大致知道了數據包的組裝過程和組成,那么問題就是一次服務器發送數據包一次發多少,發多少有什么決定這個問題
-
一次發送多少個數據包?
- 當然是發送數據包越快越好,但是寬帶小,路由器過熱等等導致的可同時傳輸的數據包在一定時間是一定的,這時候再發送超過可發送上線的數據包就會導致丟包
- 最理想狀態,在線路允許情況下,達到傳輸速度最大化
- TCP協議設計了一個慢啟動機制,既開始發送較慢,根據丟包情況決定傳輸速率,不丟包增加傳輸速度,丟包就降低傳輸速度,那么傳輸多少個包的問題就得到了解決
- Linux 設定剛開始通信的時候,發送方第一次發送10個數據包,然后等待接收方的確認,默認接收方每收到2個數據包,就發送一個確認消息(ACK)
Ⅲ-HTTP 1.0 & HTTP 1.1
1.HTTP(超文本傳輸協議)簡介
真的只是簡介,是我就跳過了
-
特點
- HTTP 協議簡單,使得 HTTP服務器的程序規模小,因而通信速度很快
- HTTP 允許傳輸任意類型的數據對象。正在傳輸的類型由Content-Type加以標記
- 無連接:無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,并收到客戶的應答后,即斷開連接。采用這種方式可以節省傳輸時間
-
組成
- HTTP協議:一個基于請求與響應模式的、無狀態的、應用層的協議,常基于TCP的連接方式
2.HTTPの請求
- HTTP請求由三部分組成
- 請求行
- 消息報頭
- 請求正文
-
請求行
- 請求行以一個方法符號開頭,以空格分開,后面跟著請求的 URI 和協議的版本,格式如下:Method Request-URI(統一資源標識符,既URL) HTTP-Version CRLF(表示回車和換行)
- 請求方法-Method
* GET & POST (我也就只用過這兩個....)
* HEAD作用: 只請求資源的首部/檢查超鏈接的有效性/檢查網頁是否被修改
* PUT:請求服務器存儲一個資源
* DELETE 請求服務器刪除一個資源
* TRACE 請求服務器回送收到的請求消息,主要用于測試或者診斷
* CONNECT (Keep-Alive)
* OPTIONS 請求查詢服務區的性能,查詢與資源相關的選項和需求
3.HTTPの響應
- HTTP響應也是由三個部分組成,分別是:狀態行、消息報頭、響應正文
- 狀態行
- 格式: HTTP-Version Status-Code Reason-Phrase(表示狀態代碼的文本描述) CRLF
- status-code
* 200 OK //客戶端請求成功
* 400 Bad Request //客戶端請求有語法錯誤,不能被服務器所理解
* 401 Unauthorized //請求未經授權,這個狀態代碼必須和
WWW-Authenticate 一起使用
* 403 Forbidden //服務器收到請求,但是拒絕提供服務
* 404 Not Found //請求資源不存在,eg:輸入了錯誤的 URL
* 500 Internal Server Error //服務器發生不可預期的錯誤
* 503 Server Unavailable//服務器當前不能處理客戶端的請求,一段時間后,//可能恢復正常
- 消息報頭
* Accept:用于指定客戶端接受哪些類型的信息
* Accept-Charset 請求報頭域用于指定客戶端接受的字符集 (未設置,則是任何字符集都可接受)
* Accept-Encoding 可接受的內容編碼,沒有服務器假定客戶端對各種內容編 碼都可以接受
* Accept-Language
* Authorization 當瀏覽器訪問一個頁面時 ,如 果收到服務器的響應代碼為 401(未授權),可以發送一個包含 Authorization,要求服務器對其進行驗證。
* Host(必需)
* User-Agent
4.補充
- 高層協議
- 文件傳輸協議 FTP
- 電子郵件傳輸協議 SMTP
- 域名系統服務 DNS
- 網絡新聞傳輸協議NNTP
this is so boring.JPG
Ⅳ-HTTP 2.0
- 重點來了,打起精神來
1. HTTP 2.0 需要解決什么問題
1. 相對于使用 TCP 的HTTP1.1,用戶在大多數情況下的感知延遲要有實質上、可度量的改進;
2. 解決 HTTP 中的“隊首阻塞”問題;
> 隊首阻塞會在下面的HTTP Pipelining解釋
3. 并行操作無需與服務器建立多個連接,從而改進TCP的利用率,特別是擁塞控制方面;
4. 保持 HTTP 1.1 的語義,利用現有文檔,包括(但不限于)HTTP 方法、狀態碼、URI,以及首部字段(既向下兼容)
5. 解決突破HTTP1.0 & HTTP1.1 的性能限制,改進傳輸性能,實現低延遲和高吞吐量
2.主要改變
- 通過支持首部字段壓縮和在同一連接上發送多個并發消息,讓應用更有效地利用網絡資源,減少感知的延遲時間。而且,它還支持服務器到客戶端的主動推送機制
3.二進制分幀數據層
- 作用:封裝HTTP消息,并在客戶端與服務器之間傳輸,將所有傳輸的信息分割為更小的消息和幀,并對它們采用二進制格式的編碼
- 組成:幀 & 消息 & 流
1. 組成:流既通道,通道內雙向傳輸消息,消息由幀組成
2. 流:連接中的一個虛擬信道,可以承載雙向的消息;每個流都有一個唯一的整數標識符(1、2…n)
3. 消息:是指邏輯上的HTTP消息,比如請求、響應等,由一或多個幀組成
4. 幀:HTTP 2.0 通信的最小單位,每個幀包含幀首部,至少也會標識出當前幀所屬的流,承載著特定類型的數據,如HTTP的header 負荷等等,**所有首部數據都會被壓縮**
- 二進制分幀層實現了多項請求和響應,可以把消息分級為互不依賴的幀,亂序發送
1. 可以并行交錯地發送請求,請求之間互不影響;
2. 可以并行交錯地發送響應,響應之間互不干擾;
3. 只使用一個連接即可并行發送多個請求和響應;
4. 消除不必要的延遲,從而減少頁面加載的時間;
5. 不必再為繞過 HTTP 1.x 限制而多做很多工作
- 作用
- HTTP 2.0 的二進制分幀機制解決了HTTP1.x中存在的隊首阻塞問題,也消除了并行處理和發送請求及響應時對多個連接的依賴。
- 有了新的分幀機制后,HTTP 2.0不再依賴多個TCP連接去實現多流并行了。每個數據流都拆分成很多幀,而這些幀可以交錯,還可以分別優先級。HTTP2.0連接都是持久化的,而且客戶端與服務器之間也只需要一個連接即可。
- 大多數HTTP 連接的時間都很短,而且是突發性的,但TCP 只在長時間連接傳輸大塊數據時效率才最高。HTTP 2.0 通過讓所有數據流共用同一個連接,可以更有效地使用TCP 連接。
4.服務器推送
- HTTP 2.0 新增的一個強大的新功能,就是服務器可以對一個客戶端請求發送多個響應。服務器向客戶端推送資源無需客戶端明確地請求
5.HTTP Pipelining
- HTTP Pipelining:其實是把多個HTTP請求放到一個TCP連接中一一發送,而在發送過程中不需要等待服務器對前一個請求的響應;只不過,客戶端還是要按照發送請求的順序來接收響應。但就像在超市收銀臺或者銀行柜臺排隊時一樣,你并不知道前面的顧客是干脆利索的還是會跟收銀員/柜員磨蹭到世界末日(譯者注:不管怎么說,服務器(即收銀員/柜員)是要按照順序處理請求的,如果前一個請求非常耗時(顧客磨蹭),那么后續請求都會受到影響),這就是所謂的隊首阻塞(Head of line blocking)。
V-結論
- 如果面試官問的問題是基于TCP協議,那么我認為:多次請求是可以保持一次連接的,因為每次創建新的TCP連接很占資源和性能
- 如果面試官問的問題是基于HTTP1.x協議,那么如果在設置connection:keep-alive的前提下,是存在多次請求保持一次連接的,但針對同一域名的請求有一定的數量限制(maxKeepAliveRequests),超過限制的請求會被阻塞,我覺得多次請求保持一次連接是不能保證的,且存在系統資源無效占用等問題,還要設置connectionTimeout最大間隔時間,如果超過最大時間間隔,連接會被關閉,所以在不設置的前提下,只有一次連接我是不服氣的
- 如果面試官問的問題是基于HTTP2協議,那呢我認為:是一次連接的,二進制分幀層解決了雙向并行交錯地發送請求和響應,而且優化延遲也是通過減少創建TCP連接而設計的
so,這個面試官給的肯定回答也只是五五開嘍!!!(盧姥爺曾經而是體面人~)
Ⅵ 參考文檔
- TCP
- HTTP 2.0