HTTP
- 超文本傳輸協議(HyperText Transfer Protocol)
- 客戶端與服務器應答標準
- 基于TCP/IP協議的應用層協議
- 91年發布HTTP/0.9,96年HTTP/1.0, 99年HTTP/1.1
- 2015年HTTP/2 Spec 發布 RFC 7540
HTTP/0.9 - HTTP/1.1
- 0.9僅有一個Get方法
- 1.0增加若干內容如Post Head,不支持永久TCP連接...
- 1.1版本增加更多內容,支持持久連接,管道機制,緩存...
HTTP面臨的問題
- TCP不能夠充分被利用
- 網絡差就會延遲
- 目前優化HTTP的方案都比較繁瑣
- HTTP包含太多的細節和可選部分,過于龐大
- HTTP Pipelinging(通過管線提高TCP利用率),會隊頭阻塞(Head-of-line blocking)
- 延遲,HTTP Streaming延遲
- 請求的內容越來越大
目前的解決方法
- 合并腳本
- 樣式表
- 圖片嵌入CSS
- 域名分片
SPDY(Speed)
- 由Google開發,設計目的在于降低網頁的加載時間
- SPDY不用于替換HTTP,只是修改了HTTP的傳輸方式
- 有多路復用,優先級,和壓縮的特性
- 僅支持在TLS(安全傳輸層協議)層
- SPDY是Google的注冊商標
HTTP/2
- 基于SPDY草案修改
- 在現有協議上之上構建的新協議,保留現有
- 更好的利用TCP特性來減少傳輸過程中的等待和暫停
- 更好的Web體驗
- HTTP/2 是google開發的 SPDY協議的一個子集
- 解決隊頭阻塞(Head-of-line blocking)問題
- 下一個協議是HTTP/3
- RFC 7540
HTTP/2特性
與HTTP1.x兼容
使用NPN或者ALPN在請求之前確定應該如何使用哪種協議來通訊.
- ALPN(Application Layer Protocol Negotiation)(HTTP2)
- NPN(Next Protocol Negotiation)(SYPD)
NPN與ALPN的區別在于: 誰來決定會話所使用的協議
ALPN:客戶端先發送一個協議優先級列表給服務器,有服務器選擇合適的
NPN:服務通知客戶端所有它支持的格式,客戶端來選合適的進行通信
NPN已經被ALPN取代
二進制協議
- HTTP由文本協議變成二進制協議
- 為了更好的實現成幀,使用文本再數據處理會很繁瑣
- 一個幀包含數據幀和頭幀
-
使用curl或者Wireshark來解析
幀
- 連接建立之后之后用幀來傳輸數據
- Length表示幀的大小
- Type類型定義了剩余的幀報頭和幀主體將如何被解釋
- Flags在不同幀類型賦予不同的語義
- StreamIdentifier流的標識符號,用于確定是那個流的幀
- FramePayload 數據
- 目前已定義的幀有10種DATA、HEADERS、PRIORITY 、RST_STREAM、SETTINGS、PUSH_PROMISE、PING、GOAWAY、WINDOW_UPDATE、CONTINUATION
多路復用Multiplexing
- 在一個TCP連接里,可以發送多個請求或回應,可以不按照順序發送
Multiplexing 在一個TCP連接里,服務器同時收到了A請求和B請求,于是先回應A請求,結果發現處理過程非常耗時,于是就發送A請求已經處理好的部分,接著回應B請求,完成后,再發送A請求剩下的部分。 ——
數據流
- 每個請求或回應的數據包為一個流
- 每個流都會有一個StreamID,由啟動流的終端分配
- 客戶端可以定義流的并發量
優先級和依賴性
- 每個的幀頭都會包含流的優先級標識
- 可以根據優先級幀來調整已經發送的流的優先級
- 沒有明確指定使用默認值
- 流可以顯示依賴其他流
頭壓縮 HPack

- HTTP屬于無狀態協議,表示每次請求都會攜帶相同的信息,為了減少冗余信息使用了HPACK機制來對請求頭進行壓縮
- 使用了默認的Static Table 和 可以由客戶端添加字段的Dynamic Table
- 使用哈夫曼編碼
- 壓縮效率高效
- RFC 7541
中斷請求
- 如果想取消一個請求只需要發送RST_STREAM 幀就可以了
服務器推送
- 可以在沒有請求的情況下主動向客戶端推送內容
- 客戶端可以選擇是否中斷推送
ServerPush-1294
HTTP連接管理
HTTP/2連接是永久性的。為了最佳的性能,它期待直到確定與服務端的進一步溝通不再必要的時候,客戶端才會關閉連接(例如,當用戶導航到其他特定的網頁),或者直到服務端關閉連接。
Chrome Debug
使用Node.js 搭建一個建議HTTP2服務器
https://github.com/molnarg/node-http2-
使用Developer Tools來查看HTTP與HTTP/2的區別
可以看出HTTP/2使用一條TCP連接完成所有的資源請求
查看HTTP/2的建立與幀傳輸
chrome://net-internals/#http2WireShark也支持抓包,不過因為HTTP/2走了TLS,所以要做一些代理處理,不做解釋。
Mobie
iOS
NSURLSession
- NSURLSession在iOS9.0之支持HTTP/2,SYPD
- 開發者不需做修改
- iOS10之后支持調試可查看請求使用的協議
- 推測通過NSURLSession通過curl實現HTTP2...(經過ida拆解只找到使用了和curl相同的HTTP/2頭解析庫??)
ASPN
- New provider API
- ASPN服務使用HTTP/2來實現,通過減少TCP連接大幅度提升服務器效率,減少服務端壓力
總結
iOS同學基本上,如果使用了URLSession去做網絡請求可以啥都不用干,只要Server支持HTTP/2就可以了
Android
沒有寫過安卓...本部分僅參考
OKHttp
- 安卓端的一個HTTP的實現
- JAVA實現了HTTP/2
- 據Android同學SK IMSK 分享,該庫在重用TCP方面做的非常好
REF
http://kamranahmed.info/blog/2016/08/13/http-in-depth/ HTTP協議簡介
https://github.com/square/okhttp 安卓Http網絡請求的實現
https://github.com/kylef/hpack.swift hpackSwift實現
https://github.com/curl/curl libcurl
https://github.com/nghttp2/nghttp2 curl里HPack的實現
https://github.com/apple/swift-corelibs-foundation Swift版本Foundation實現
http://opensource.apple.com/source/CF/CF-1153.18/
https://http2.github.io/
http://httpwg.org/specs/rfc7540.html RFC7540 HTTP2.0詳細實現
http://www.chromium.org/spdy/spdy-whitepaper
https://developer.apple.com/videos/play/wwdc2016/711/ NSURLSession: New Features and Best Practices
https://developer.apple.com/videos/play/wwdc2015/711/ Networking with NSURLSession
https://developer.apple.com/videos/play/wwdc2015/720/ What’s New in Notifications
https://developer.apple.com/videos/play/wwdc2015/724/
What’s New in Apple Push Notification Service