聶永的博客

          記錄工作/學習的點點滴滴。

          HTTP/2筆記之幀

          零。前言

          客戶端和服務器端一旦握手協商成功接建立連接,端點之間可以基于HTTP/2協議傳遞交換幀數據了。

          一。幀通用格式

          下圖為HTTP/2幀通用格式:幀頭+負載的比特位通用結構:

          +-----------------------------------------------+
          |                Length (24)                    |
          +---------------+---------------+---------------+
          |  Type (8)     |  Flags (8)    |
          +-+-------------+---------------+-------------------------------+
          |R|                Stream Identifier (31)                       |
          +=+=============================================================+
          |                  Frame Payload (0...)                       ...
          +---------------------------------------------------------------+

          幀頭為固定的9個字節((24+8+8+1+31)/8=9)呈現,變化的為幀的負載(payload),負載內容是由幀類型(Type)定義。

          • 幀長度Length:無符號的自然數,24個比特表示,僅表示幀負載所占用字節數,不包括幀頭所占用的9個字節。默認大小區間為為0~16,384(2^14),一旦超過默認最大值2^14(16384),發送方將不再允許發送,除非接收到接收方定義的SETTINGS_MAX_FRAME_SIZE(一般此值區間為2^14 ~ 2^24)值的通知。
          • 幀類型Type:8個比特表示,定義了幀負載的具體格式和幀的語義,HTTP/2規范定義了10個幀類型,這里不包括實驗類型幀和擴展類型幀
          • 幀的標志位Flags:8個比特表示,服務于具體幀類型,默認值為0x0。有一個小技巧需要注意,一般來講,8個比特可以容納8個不同的標志,比如,PADDED值為0x8,二進制表示為00001000;END_HEADERS值為0x4,二進制表示為00000100;END_STREAM值為0X1,二進制為00000001。可以同時在一個字節中傳達三種標志位,二進制表示為00001101,即0x13。因此,后面的幀結構中,標志位一般會使用8個比特表示,若某位不確定,使用問號?替代,表示此處可能會被設置標志位
          • 幀保留比特為R:在HTTP/2語境下為保留的比特位,固定值為0X0
          • 流標識符Stream Identifier:無符號的31比特表示無符號自然數。0x0值表示為幀僅作用于連接,不隸屬于單獨的流。

          關于幀長度,需要稍加關注: - 0 ~ 2^14(16384)為默認約定長度,所有端點都需要遵守 - 2^14 (16,384) ~ 2^24-1(16,777,215)此區間數值,需要接收方設置SETTINGS_MAX_FRAME_SIZE參數單獨賦值 - 一端接收到的幀長度超過設定上限或幀太小,需要發送FRAME_SIZE_ERR錯誤 - 當幀長錯誤會影響到整個連接狀態時,須以連接錯誤對待之;比如HEADERS,PUSH_PROMISE,CONTINUATION,SETTINGS,以及幀標識符不該為0的幀等,都需要如此處理 - 任一端都沒有義務必須使用完一個幀的所有可用空間 - 大幀可能會導致延遲,針對時間敏感的幀,比如RST_STREAM, WINDOW_UPDATE, PRIORITY,需要快速發送出去,以免延遲導致性能等問題

          二。報文頭壓縮和解壓

          和HTTP/1一樣,HTTP/2報頭字段包含一個或多個相關的鍵值對。報頭字段會在HTTP請求/響應報頭和服務器推送操作中使用。原先為文本字段,現在需要使用HTTP報頭壓縮進行序列化成報頭分塊,作為HEADERS 、 PUSH_PROMISE、CONTINUATION等幀的負載傳輸出去。

          解壓縮采用的HPACK協議,具體可參考:http://http2.github.com/http2-spec/compression.html

          接收端合并接收到的幀組裝成報頭分塊,解壓縮還原報頭集合。

          一個完整的報頭分塊包含: - 單個包含報頭終止標記END_HEADERS的HEADERS、PUSH_PROMISE幀,或者 - HEADERS、PUSH_PROMISE幀不包含的END_HEADERS標記,后續跟隨一個或多個CONTINUATION幀,最后一個CONTINUATION幀包含了END_HEADERS標記。

          報頭壓縮是有狀態的,在一個完整的連接中,一方的壓縮上下文環境,另一方的解壓的上下文環境,都是需要具備的。報頭解碼失敗需要作為連接錯誤COMPRESSION_ERROR對待。

          報頭塊彼此之間離散,作為連續的同一類型幀序列存在,不存在交錯幀以及來自其他類型幀或流。舉一個例子,一個連續的HEADERS/CONTINUATION/PUSH_PROMISE幀序列,最后一個幀包含了END_HEADERS標記,表示一個報頭完結。一個報頭塊邏輯上是一個幀,但是否完整取決于同類型連續的幀的最后一個包含END_HEADERS標記。

          報頭塊作為HEADERS/PUSH_PROMISE/CONTINUATION等幀負載被一端發向另一端。接收端需要從HEADERS/PUSH_PROMISE/CONTINUATION等幀負載中進行組裝報頭塊,執行解壓還原報頭集合,不管幀需要不需要被丟棄。接收端在解壓時若不能夠正常解壓報頭塊,需要回應COMPRESSION_ERROR錯誤,然后終止連接。

          三。HTTP/2定義的幀

          規范定義了10個正式使用到幀類型,擴展實驗類型的ALTSVC、BLOCKED等不在介紹之列。下面按照優先使用順序重新排排序。

          1. SETTINGS

          +-----------------------------------------------+
          |                Length (24)                    |
          +---------------+---------------+---------------+
          |     0x4 (8)   | 0000 000? (8) |
          +-+-------------+---------------+-------------------------------+
          |R|                Stream Identifier/0x0 (32)                   |
          +=+=============================+===============================+
          |       Identifier (16)         |
          +-------------------------------+-------------------------------+
          |                        Value (32)                             |
          +---------------------------------------------------------------+
          |       Identifier (16)         |
          +-------------------------------+-------------------------------+
          |                        Value (32)                             |
          +---------------------------------------------------------------+  

          設置幀,接收者向發送者通告己方設定,服務器端在連接成功后必須第一個發送的幀。

          字段Identifier定義了如下參數: - SETTINGS_HEADER_TABLE_SIZE (0x1),通知接收者報頭表的字節數最大值,報頭塊解碼使用;初始值為4096個字節,默認可不用設置 - SETTINGS_ENABLE_PUSH (0x2),0:禁止服務器推送,1:允許推送;其它值非法,PROTOCOL_ERROR錯誤 - SETTINGS_MAX_CONCURRENT_STREAMS (0x3),發送者允許可打開流的最大值,建議值100,默認可不用設置;0值為禁止創建新流 - SETTINGS_INITIAL_WINDOW_SIZE (0x4),發送端流控窗口大小,默認值2^16-1 (65,535)個字節大小;最大值為2^31-1個字節大小,若溢出需要報FLOW_CONTROL_ERROR錯誤 - SETTINGS_MAX_FRAME_SIZE (0x5),單幀負載最大值,默認為2^14(16384)個字節,兩端所發送幀都會收到此設定影響;值區間為2^14(16384)-2^24-1(16777215) - SETTINGS_MAX_HEADER_LIST_SIZE (0x6),發送端通告自己準備接收的報頭集合最大值,即字節數。此值依賴于未壓縮報頭字段,包含字段名稱、字段值以及每一個報頭字段的32個字節的開銷等;文檔里面雖說默認值不受限制,因為受到報頭集合大小不限制的影響,個人認為不要多于2 SETTINGS_MAX_FRAME_SIZE(即2^142=32768),否則包頭太大,隱患多多。

          標志位: * ACK (0x1),表示接收者已經接收到SETTING幀,作為確認必須設置此標志位,此時負載為空,否則需要報FRAME_SIZE_ERROR錯誤

          注意事項: - 在連接開始階段必須允許發送SETTINGS幀,但不一定要發送 - 在連接的生命周期內可以允許任一端點發送 - 接收者不需要維護參數的狀態,只需要記錄當前值即可 - SETTINGS幀僅作用于當前連接,不針對單個流,因此流標識符為0x0 - 不完整或不合規范的SETTINGS幀需要拋出PROTOCOL_ERROR類型連接錯誤 - 負載字節數為6個字節的倍數,6*N (N>=0)

          處理流程: - 發送端發送需要兩端都需要攜帶有遵守的SETTINGS設置幀,不能夠帶有ACK標志位 - 接收端接收到無ACK標志位的SETTINGS幀,必須按照幀內字段出現順序一一進行處理,中間不能夠處理其它幀 - 接收端處理時,針對不受支持的參數需忽略 - 接收端處理完畢之后,必須響應一個包含有ACK確認標志位、無負載的SETTINGS幀 - 發送端接收到確認的SETTINGS幀,表示兩端設置已生效 - 發送端等待確認若超時,報SETTINGS_TIMEOUT類型連接錯誤

          2. HEADER

          +-----------------------------------------------+
          |                Length (24)                    |
          +---------------+---------------+---------------+
          |    0x1 (8)    | 00?0 ??0? (8) |
          +-+-------------+---------------+-------------------------------+
          |R|                Stream Identifier (31)                       |
          +=+=============+===============================================+
          |Pad Length? (8)|
          +-+-------------+-----------------------------------------------+
          |E|                 Stream Dependency? (31)                     |
          +-+-------------+-----------------------------------------------+
          |  Weight? (8)  |
          +-+-------------+-----------------------------------------------+
          |                   Header Block Fragment (*)                 ...
          +---------------------------------------------------------------+
          |                           Padding (*)                       ...
          +---------------------------------------------------------------+

          報頭主要載體,請求頭或響應頭,同時呢也用于打開一個流,在流處于打開"open"或者遠程半關閉"half closed (remote)"狀態都可以發送。

          字段列表: - Pad Length:受制于PADDED標志控制是否顯示,8個比特表示填充的字節數。 - E:一個比特表示流依賴是否專用,可選項,只在流優先級PRIORITY被設置時有效 - Stream Dependency:31個比特表示流依賴,只在流優先級PRIORITY被設置時有效 Weight:8個比特(一個字節)表示無符號的自然數流優先級,值范圍自然是(1~256),或稱之為權重。只在流優先級PRIORITY被設置時有效 - Header Block Fragment:報頭塊分片 - Padding:填充的字節,受制于PADDED標志控制是否顯示,長度由Pad Length字段決定

          所需標志位: END_STREAM (0x1): 報頭塊為最后一個,意味著流的結束。后續可緊接著CONTINUATION幀在當前的流中,需要把CONTINUATION幀作為HEADERS幀的一部分對待 END_HEADERS (0x4): 此報頭幀不需分片,完整的一個幀。后續不再需要CONTINUATION幀幫忙湊齊。若沒有此標志的HEADER幀,后續幀必須是以CONTINUATION幀傳遞在當前的流中,否則接收者需要響應PROTOCOL_ERROR類型的連接錯誤。 PADDED (0x8): 需要填充的標志 PRIORITY (0x20): 優先級標志位,控制獨立標志位E,流依賴,和流權重。

          注意事項: - 其負載為報頭塊分片,若內容過大,需要借助于CONTINUATION幀繼續傳輸。若流標識符為0x0,結束段需要返回PROTOCOL_ERROR連接異常。HEADERS幀包含優先級信息是為了避免潛在的不同流之間優先級順序的干擾。 - 其實一般來講,報文頭部不大的情況下,一個HEADERS就可以完成了,特殊情況就是Cookie字段超過16KiB大小,不常見。

          3. CONTINUATION

          +-----------------------------------------------+
          |                Length (24)                    |
          +---------------+---------------+---------------+
          |  0x9 (8)      |  0x0/0x4  (8) |
          +-+-------------+---------------+-------------------------------+
          |R|                Stream Identifier (32)                       |
          +=+=============================================================+
          |                  Header Block Fragment (*)                    |
          +---------------------------------------------------------------+

          字段列表: - Header Block Fragment,用于協助HEADERS/PUSH_PROMISE等單幀無法包含完整的報頭剩余部分數據。

          注意事項: - 一個HEADERS/PUSH_PROMISE幀后面會跟隨零個或多個CONTINUATION,只要上一個幀沒有設置END_HEADERS標志位,就不算一個幀完整數據的結束。 - 接收端處理此種情況,從開始的HEADERS/PUSH_PROMISE幀到最后一個包含有END_HEADERS標志位幀結束,合并的數據才算是一份完整數據拷貝 - 在HEADERS/PUSH_PROMISE(沒有END_HEADERS標志位)和CONTINUATION幀中間,是不能夠摻雜其它幀的,否則需要報PROTOCOL_ERROR錯誤

          標志位: * END_HEADERS(0X4):表示報頭塊的最后一個幀,否則后面還會跟隨CONTINUATION幀。

          4. DATA

          一個或多個DATA幀作為請求、響應內容載體,較為完整的結構如下:

          +-----------------------------------------------+
          |                Length (24)                    |
          +---------------+---------------+---------------+
          | 0x0 (8)       | 0000 ?00? (8) |
          +-+-------------+---------------+-------------------------------+
          |R|                Stream Identifier (31)                       |
          +=+=============+===============================================+
          |Pad Length? (8)|
          +---------------+-----------------------------------------------+
          |                            Data (*)                         ...
          +---------------------------------------------------------------+
          |                          Padding? (*)                       ...
          +---------------------------------------------------------------+

          字段: Pad Length: 一個字節表示填充的字節長度。取決于PADDED標志是否被設置. Data: 這里是應用數據,真正大小需要減去其他字段(比如填充長度和填充內容)長度。 * Padding: 填充內容為若干個0x0字節,受PADDED標志控制是否顯示。接收端處理時可忽略驗證填充內容。若驗證,可以對非0x0內容填充回應PROTOCOL_ERROR類型連接異常。

          標志位: END_STREAM (0x1): 標志此幀為對應標志流最后一個幀,流進入了半關閉/關閉狀態。 PADDED (0x8): 負載需要填充,Padding Length + Data + Padding組成。

          注意事項: - 若流標識符為0x0,接收者需要響應PROTOCOL_ERROR連接錯誤 - DATA幀只能在流處于"open" or "half closed (remote)"狀態時被發送出去,否則接收端必須響應一個STREAM_CLOSED的連接錯誤。若填充長度不小于負載長度,接收端必須響應一個PROTOCOL_ERROR連接錯誤。

          5. PUSH_PROMISE

          +-----------------------------------------------+
          |                Length (24)                    |
          +---------------+---------------+---------------+
          |  0x5 (8)      | 0000 ??00 (8) |
          +-+-------------+---------------+-------------------------------+
          |R|                Stream Identifier (32)                       |
          +=+=============================================================+
          |Pad Length? (8)|
          +-+-------------+-----------------------------------------------+
          |R|                Promised Stream ID (31)                      |
          +-+-------------------------------------------------------------+
          |                  Header Block Fragment (*)                . . .
          +---------------------------------------------------------------+
          |                           Padding (*)                     . . .
          +---------------------------------------------------------------+

          服務器端通知對端初始化一個新的推送流準備稍后推送數據: - 要求推送流為打開或遠端半關閉(half closed (remote))狀態,否則報PROTOCOL_ERROR錯誤: - 承諾的流不一定要按照其流打開順序進行使用,僅用作稍后使用 - 受對端所設置SETTINGS_ENABLE_PUSH標志位決定是否發送,否則作為PROTOCOL_ERROR錯誤對待 - 接收端一旦拒絕接收推送,會發送RST_STREAM幀告知對方推送無效

          字段列表: - Promised Stream ID,31個比特表示無符號的自然數,為推送保留的流標識符,后續適用于發送推送數據 - Header Block Fragment,請求頭部字段值,可看做是服務器端模擬客戶端發起一次資源請求

          標志位: END_HEADERS(0x4/00000010),此幀包含完整的報頭塊,不用后面跟隨CONTINUATION幀了 PADDED(0x8/00000100),填充開關,決定了下面的Pad Length和Padding是否要填充,具體和HEADERS幀內容一致,不多說

          6. PING

          優先級幀,類型值為0x6,8個字節表示。發送者測量最小往返時間,心跳機制用于檢測空閑連接是否有效。

          +-----------------------------------------------+
          |                0x8 (24)                       |
          +---------------+---------------+---------------+
          |  0x6 (8)      | 0000 000? (8) |
          +-+-------------+---------------+-------------------------------+
          |R|                          0x0 (32)                           |
          +=+=============================================================+
          |                        Opaque Data (64)                       |
          +---------------------------------------------------------------+

          字段列表: - Opaque Data:8個字節負載,值隨意填寫。

          標志位: * ACK(0x1):一旦設置,表示此PING幀為接收者響應的PING幀,非發送者。

          注意事項: - PING幀發送方ACK標志位為0x0,接收方響應的PING幀ACK標志位為0x1。否則直接丟棄。其優先級要高于其它類型幀。 - PING幀不和具體流相關聯,若流標識符為0x0,接收方需要響應PROTOCOL_ERROR類型連接錯誤。 - 超過負載長度,接收者需要響應FRAME_SIZE_ERROR類型連接錯誤。

          7. PRIORITY

          優先級幀,類型值為0x2,5個字節表示。表達了發送方對流優先級權重的建議值,在流的任何狀態下都可以發送,包括空閑或關閉的流。

          +-----------------------------------------------+
          |                   0x5 (24)                    |
          +---------------+---------------+---------------+
          |   0x2 (8)     |    0x0 (8)    |
          +-+-------------+---------------+-------------------------------+
          |R|                  Stream Identifier (31)                     |
          +=+=============================================================+
          |E|                  Stream Dependency (31)                     |
          +-+-------------+-----------------------------------------------+
          | Weight (8)    |
          +---------------+

          字段列表: - E:流是否獨立 - Stream Dependency:流依賴,值為流的標識符,自然也是31個比特表示。 - Weight:權重/優先級,一個字節表示自然數,范圍1~256

          注意事項: - PRIORITY幀其流標識符為0x0,接收方需要響應PROTOCOL_ERROR類型的連接錯誤。 - PRIORITY幀可在流的任何狀態下發送,但限制是不能夠在一個包含有報頭塊連續的幀里面出現,其發送時刻需要,若流已經結束,雖然可以發送,但已經沒有什么效果。 - 超過5個字節PRIORITY幀接收方響應FRAME_SIZE_ERROR類型流錯誤。

          8. WINDOW_UPDATE

          +-----------------------------------------------+
          |                0x4 (24)                       |
          +---------------+---------------+---------------+
          |   0x8 (8)     |    0x0 (8)    |
          +-+-------------+---------------+-------------------------------+
          |R|                Stream Identifier (31)                       |
          +=+=============================================================+
          |R|              Window Size Increment (31)                     |
          +-+-------------------------------------------------------------+

          流量控制幀,作用于單個流以及整個連接,但只能影響兩個端點之間傳輸的DATA數據幀。但需注意,中介不轉發此幀。

          字段列表: - Window Size Increment,31個比特位無符號自然數,范圍為1-2^31-1(2,147,483,647)個字節數,表明發送者可以發送的最大字節數,以及接收者可以接收到的最大字節數。

          注意事項: - 目前流控只會影響到DATA數據幀 - 流標識符為0,影響整個連接,非單個流 - 流標識符不為空,具體流的標識符,將只能夠影響到具體流 - WINDOW_UPDATE在某個攜帶有END_STREAM幀的后面被發送(當前流處于關閉或遠程關閉狀態),接收端可忽略,但不能作為錯誤對待 - 發送者不能發送一個窗口值大于接收者已持有(接收端已經擁有一個流控窗口值)可用空間大小的WINDOW_UPDATE幀 - 當流控窗口所設置可用空間已耗盡時,對端發送一個零負載帶有END_STREAM標志位的DATA數據幀,這是允許的行為 - 流量控制不會計算幀頭所占用的9個字節空間 - 若窗口值溢出,針對單獨流,響應RST_STREAM(錯誤碼FLOW_CONTROL_ERROR)幀;針對整個連接的,響應GOAWAY(錯誤碼FLOW_CONTROL_ERROR)幀 - DATA數據幀的接收方在接收到數據幀之后,需要計算已消耗的流控窗口可用空間,同時要把最新可用窗口空間發送給對端 - DATA數據幀發送方接收到WINDOW_UPDATE幀之后,獲取最新可用窗口值 - 接收方異步更新發送方窗口值,避免流停頓/失速 - 默認情況下流量控制窗口值為65535,除非接收到SETTINGS幀SETTINGS_INITIAL_WINDOW_SIZE參數,或者WINDOWS_UPDATE幀攜帶的窗口值大小,否則不會改變 - SETTINGS_INITIAL_WINDOW_SIZE值的改變會導致窗口可用空間不明晰,易出問題,發送者必須停止受流控影響的DATA數據幀的發送直到接收到WINDOW_UPDATE幀獲得新的窗口值,才會繼續發送。eg:客戶端在連接建立的瞬間一口氣發送了60KB的數據,但來自服務器SETTINGS設置幀的初始窗口值為16KB,客戶端只能夠等到WINDOW_UPDATE幀告知新的窗口值,然后繼續發送傳送剩下的44KB數據 - SETTINGS幀無法修改針對整個連接的流量控制窗口值 - 任一端點在處理SETTINGS_INITIAL_WINDOW_SIZE值時一旦導致流控窗口值超出最大值,都需要作為一個FLOW_CONTROL_ERROR類型連接錯誤對待

          9. RST_STREAWM

          優先級幀,類型值為0x3,4個字節表示。表達了發送方對流優先級權重的建議值,任何時間任何流都可以發送,包括空閑或關閉的流。

          +-----------------------------------------------+
          |                0x4 (24)                       |
          +---------------+---------------+---------------+
          |  0x3  (8)     |  0x0 (8)      |
          +-+-------------+---------------+-------------------------------+
          |R|                Stream Identifier (31)                       |
          +=+=============================================================+
          |                        Error Code (32)                        |
          +---------------------------------------------------------------+

          字段列表: - Error Code:錯誤代碼,32位無符號的自然數表示流被關閉的錯誤原因。

          注意事項: - 接收到RST_STREAM幀,需要關閉對應流,因此流也要處于關閉狀態。 - 接收者不能夠在此流上發送任何幀。 - 發送端需要做好準備接收接收端接收到RST_STREAM幀之前發送的幀,這個空隙的幀需要處理。 - 若流標識符為0x0,接收方需要響應PROTOCOL_ERROR類型連接錯誤。 - 當流處于空閑狀態idle狀態時是不能夠發送RST_STREAM幀,否則接收方會報以PROOTOCOL_ERROR類型連接錯誤。

          10. GOAWAY

          +-----------------------------------------------+
          |                Length (24)                    |
          +---------------+---------------+---------------+
          |  0x7 (8)      |     0x0 (8)   |
          +-+-------------+---------------+-------------------------------+
          |R|                Stream Identifier (32)                       |
          +=+=============================================================+
          |R|                  Last-Stream-ID (31)                        |
          +-+-------------------------------------------------------------+
          |                      Error Code (32)                          |
          +---------------------------------------------------------------+
          |                  Additional Debug Data (*)                    |
          +---------------------------------------------------------------+

          一端通知對端較為優雅的方式停止創建流,同時還要完成之前已建立流的任務。

          • 一旦發送,發送者將忽略接收到的流標識符大于Last-Stream-ID任何幀
          • 接收者不能夠在當前流上創建新流,若創建新流則創建新的連接
          • 可用于服務器的管理行為,比如服務器進入維護階段,不再準備接收新的連接
          • 字段Last-Stream-ID為發送方取自最后一個正在處理或已經處理流的標識符
          • 后續創建的流標識符高于Last-Stream-ID數據幀都不會被處理
          • 終端應被鼓勵在關閉連接之前發送GOAWAY隱式方式告知對方某些流是否已經被處理
          • 終端可以選擇關閉連接,針對行為不當的終端不發送GOAWAY幀
          • GOAWAY應用于當前連接,非具體流
          • 沒有處理任何流的情況下,Last-Stream-ID值可為0,也是合法
          • 流(標識符小于或等于已有編號的標識符)在連接關閉之前沒有被完全關閉,需要創建新的連接進行重試
          • 發送端在發送GOAWAY時還有一些流任務沒有完成,將保持連接為打開狀態直到任務完成
          • 終端可以在自身環境發生改變時發送多個GOAWAY幀,但Last-Stream-ID不允許增長
          • Additional Debug Data沒有語義,僅用于聯機測試診斷目的。若攜帶登陸或持久化調試數據,需要有安全保證避免未經授權訪問。

          四。幀的擴展

          HTTP/2協議的擴展是允許存在的,在于提供額外服務。擴展包括: - 新類型幀,需要遵守通用幀格式 - 新的設置參數,用于設置新幀相關屬性 - 新的錯誤代碼,約定幀可能觸發的錯誤

          當定義一個新幀,需要注意 1. 規范建議新的擴展需要經過雙方協商后才能使用 1. 在SETTINGS幀添加新的參數項,可在連接序言時發送給對端,或者適當機會發送 1. 雙方協商成功,可以使用新的擴展

          已知ALTSVC、BLOCKED屬于擴展幀。

          1. ALTSVC

          服務器提供給客戶端當前可用的替代服務,類似于CNAME,客戶端不支持可用選擇忽略

          +-----------------------------------------------+
          |                Length (24)                    |
          +---------------+---------------+---------------+
          |  0xa (8)      |     0x0 (8)   |
          +-+-------------+---------------+-------------------------------+
          |R|                Stream Identifier (32)                       |
          +=+=============================+===============================+
          |         Origin-Len (16)       | Origin? (*)                 ...
          +-------------------------------+-------------------------------+
          |                   Alt-Svc-Field-Value (*)                   ...
          +---------------------------------------------------------------+

          字段列表: - Origin-Len: 16比特位整數,說明了Origin字段字節數 - Origin: ASCII字符串表示替代服務 - Alt-Svc-Field-Value: 包含了Alt-Svc HTTP Header Field,長度=Length (24) - Origin-Len (16)

          需要注意: - 中介設備不能轉發給客戶端,原因就是中介自身替換處理,轉發正常的業務數據給客戶端就行

          具體可參考:https://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-06

          2. BLOCKED

          一端告訴另一端因為受到流量控制的作用有數據但無法發送。

          +-----------------------------------------------+
          |                Length (24)                    |
          +---------------+---------------+---------------+
          |  0xb (8)      |     0x0 (8)   |
          +-+-------------+---------------+-------------------------------+
          |R|                Stream Identifier/0x0 (32)                   |
          +=+=============================================================+
          • Stream Identifier若為0x0,則表示針對整個連接,否則針對具體流
          • 在流量控制窗口生效之前不能發送BLOCKED
          • 一旦遇到此項問題,說明我們的實現可能有缺陷,無法得到理想的傳輸速率
          • 只能夠在WINDOW_UPDATE幀接收之前或SETTINGS_INITIAL_WINDOW_SIZE參數增加之前發送

          五。小結

          以上記錄了HTTP/2幀基本結構,10個文檔定義的正式幀,以及額外的兩個擴展幀。

          posted on 2015-03-20 09:24 nieyong 閱讀(11759) 評論(0)  編輯  收藏 所屬分類: HTTP

          公告

          所有文章皆為原創,若轉載請標明出處,謝謝~

          新浪微博,歡迎關注:

          導航

          <2015年3月>
          22232425262728
          1234567
          891011121314
          15161718192021
          22232425262728
          2930311234

          統計

          常用鏈接

          留言簿(58)

          隨筆分類(130)

          隨筆檔案(151)

          個人收藏

          最新隨筆

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 阳山县| 屏东市| 凤翔县| 杭锦旗| 滨海县| 榆树市| 张家川| 潍坊市| 天津市| 介休市| 松溪县| 巴南区| 冀州市| 浮梁县| 大新县| 虹口区| 武川县| 邵武市| 旌德县| 滁州市| 弋阳县| 栖霞市| 旺苍县| 桐梓县| 宝丰县| 上高县| 麻阳| 北川| 眉山市| 江源县| 前郭尔| 武胜县| 宝应县| 叶城县| 双峰县| 舟曲县| 泌阳县| 措勤县| 武安市| 浏阳市| 元江|