Jump to content

5.3. 立即關閉應用程序HTTP/3實現可以在任何時候立即關閉QUIC連接。這將導致向對等方發送一個QUIC CONNECTION_CLOSE幀,這表明應用層已經終止了連接。此幀中的應用程序錯誤代碼向對等方表明連接被關閉的原因。有關在HTTP/3 中關閉連接時可以使用的錯誤代碼,請參閱第8 節。

在關閉連接之前,可能會發送一個GOAWAY 幀以允許客戶端重試某些請求。將GOAWAY幀包含在與QUIC CONNECTION_CLOSE幀相同的包中可以提高客戶端接收幀的機會。

如果存在未明確關閉的打開流,則在關閉連接時將其悄悄關閉。

5.4. 運輸關閉由於各種原因,QUIC傳輸可以向應用層表明連接已經終止。這可能是由於對等方明確地關閉、傳輸層錯誤或中斷連接的網絡拓撲變化造成的。

如果連接在沒有GOAWAY幀的情況下終止,客戶端必須假定發送的任何請求,無論是全部的還是部分的,都可能已經被處理。

6. 流映射和使用QUIC流提供可靠的字節按順序傳遞,但不保證與其他流上的字節的傳遞順序。在QUIC的版本1中,包含HTTP幀的流數據由QUIC stream幀承載,但是這個幀對HTTP幀層是不可見的。傳輸層對接收到的流數據進行緩沖和排序,向應用程序公開可靠的字節流。雖然QUIC允許在流中無序傳遞,但HTTP/3 並未使用此功能。

QUIC 流可以是單向的,僅從發起者到接收者傳輸數據,也可以是雙向的,雙向傳輸數據。流可以由客戶端或服務器發起。

當通過QUIC 發送HTTP 字段和數據時,QUIC 層處理大部分流管理。使用QUIC 時,HTTP 不需要進行任何單獨的多路復用,通過QUIC 流發送的數據總是映射到特定的HTTP 事務或整個HTTP/3 連接上下文。

6.1雙向流所有客戶端發起的雙向流都用於HTTP請求和響應。雙向流確保響應可以很容易地與請求相關聯。這些流稱為請求流。

這意味著客戶端的第一個請求發生在QUIC流0上,隨後的請求發生在流4、流8等流中。為了允許這些流打開,HTTP/3服務器應該為允許的流數量和初始流控制窗口配置非零的最小值。為了避免不必要地限制並行性,一次至少應該允許100個請求流。

HTTP/3不使用服務器發起的雙向流,儘管擴展可以定義這些流的用途。客戶端必須將接收到服務器發起的雙向流作為H3_STREAM_CREATION_ERROR類型的連接錯誤,除非已經協商了這樣的擴展。

6.2單向流任意一個方向的單向流都可用於不同的用途。其目的由流類型表示,該流類型在流的開頭作為可變長度整數發送。這個整數後面的數據的格式和結構由流類型決定。

1.png

單向流標頭

HTTP/3連接在其生命週期的早期階段的性能對單向流上的數據創建和交換非常敏感。過度限制流的數量或這些流的流控制窗口的終端將增加遠程對等方提前達到限制並被阻止的機會。特別是,實現應該考慮遠程對等方可能希望使用他們被允許使用的一些單向流來執行保留的流行為。

每個終端都需要為HTTP控制流創建至少一個單向流。 QPACK需要兩個額外的單向流,而其他擴展可能需要更多的流。因此,客戶端和服務器端發送的傳輸參數必須允許對等方創建至少三個單向流。這些傳輸參數還應該為每個單向流提供至少1024字節的流量控制信用。

請注意,如果終端在創建關項單向流之前消耗了所有初始信用,則不需要授予額外信用來創建更多單向流。終端應該首先創建HTTP 控制流以及強制擴展所需的單向流(例如QPACK 編碼器和解碼器流),然後在其對等方允許的情況下創建其他流。

如果流標頭是接收方不支持的流類型,則無法使用流的其餘部分,因為語義未知。未知流類型的接收者必須中止讀取流或刪除傳入數據而不進行進一步處理。如果讀取被中止,接收者應該使用H3_STREAM_CREATION_ERROR 錯誤代碼或保留的錯誤代碼。接收者不得將未知流類型視為任何類型的連接錯誤。

由於某些流類型會影響連接狀態,因此接收者不應在讀取流類型之前刪除來自傳入單向流的數據。

實現可以在知道對等方是否支持它們之前發送流類型。但是,可以修改現有協議組件(包括QPACK 或其他擴展)的狀態或語義的流類型,在知道對等方支持它們之前,絕對不能發送。

除非另有說明,否則發送者可以關閉或重置單向流。接收者必須容忍單向流在接收到單向流標頭之前被關閉或重置。

6.2.1 控制流控制流由0x00流類型表示。該流上的數據由HTTP/3幀組成。

每一方必須在連接開始時初始化一個控制流,並將其SETTINGS幀作為該流的第一幀發送。如果控制流的第一幀是任何其他幀類型,則必須作為H3_MISSING_SETTINGS類型的連接錯誤處理。每個對等方只允許一個控制流;接收到第二個聲稱是控制流的流必須作為H3_STREAM_CREATION_ERROR類型的連接錯誤處理。發送方絕對不能關閉控制流,接收方也絕對不能請求發送方關閉控制流。如果任何一個控制流在任何時候被關閉,這必須作為h3_close_critical_stream類型的連接錯誤處理。

由於控制流的內容用於管理其他流的行為,終端應該提供足夠的流控制信用來防止對等方控制流被阻止。

使用一對單向流而不是一個雙向流。這允許任何一方能夠盡快發送數據。根據QUIC連接上是否有0-RTT,客戶端或服務器都可以首先發送流數據。

6.2.2 push stream服務器推送是HTTP/2中引入的一個可選特性,它允許服務器在請求發出之前發起響應。 push stream由流類型0x01指示,後面是它所實現的承諾的Push ID,編碼為可變長度整數。該流上的剩餘數據由HTTP/3幀組成,並通過零個或多個臨時HTTP響應,以及隨後的單個最終HTTP 響應來實現承諾的服務器推送。只有服務器可以推送,如果服務器接收到客戶端發起的push stream,則必須將其視為H3_STREAM_CREATION_ERROR 類型的連接錯誤。

2.png

push stream標頭

客戶端不應在讀取push stream標頭之前中止對push stream的讀取,因為這可能導致客戶端和服務器之間在已使用推送ID 的情況下出現分歧。

每個Push ID只能在push stream標頭中使用一次。如果客戶端檢測到一個push stream標頭包含在另一個push stream標頭中使用的Push ID,客戶端必須將其作為H3_ID_ERROR類型的連接錯誤處理。

6.2.3 保留流類型對於N 的非負整數值,格式為0x1f * N +0x21 的流類型被保留以執行忽略未知類型的要求。這些流沒有語義,可以在需要應用層填充時發送。它們也可以在當前沒有數據傳輸的連接上發送。終端在接收時絕對不能認為這些流有任何意義。

以發送實現選擇的任何方式選擇流的有效負載和長度。當發送保留流類型時,實現可以乾淨地終止流或重置流。當重置流時,應該使用H3_NO_ERROR錯誤碼或保留錯誤碼。

7. HTTP幀層如上所述,HTTP幀在QUIC流上傳輸。 HTTP/3定義了三種流類型:控制流、請求流和push stream。本節介紹HTTP/3 幀格式及其允許的流類型。

3.png

HTTP/3幀和流類型概述

SETTINGS幀只能作為控制流的第一幀出現,從表1(1)中可以看出。請注意,與QUIC幀不同,HTTP/3幀可以跨越多個數據包。

7.1 幀佈局所有幀都具有以下格式:

4.png

HTTP/3幀格式

每個幀包括以下字段:

類型:標識幀類型的可變長度整數。

長度:一個可變長度整數,用於描述幀有效負載的長度(以字節為單位)。

幀載荷:有效負載,其語義由Type 字段確定。

每個幀的有效負載必須準確包含在其描述中標識的字段。在已識別字段之後包含附加字節的幀有效載荷或在已識別字段結束之前終止的幀有效載荷必須被視為H3_FRAME_ERROR 類型的連接錯誤。特別是,冗余長度編碼必須經過驗證是自洽的。

當流完全終止時,如果流上的最後一幀被截斷,則必須將其視為H3_FRAME_ERROR 類型的連接錯誤。突然終止的流可以在幀中的任何點重置。

7.2 幀的定義7.2.1 數據DATA 幀(type=0x00) 傳送與HTTP 請求或響應內容相關的任意可變長度字節序列。

DATA 幀必須與HTTP 請求或響應相關聯。如果在控制流上接收到DATA 幀,接收者必須以H3_FRAME_UNEXPECTED 類型的連接錯誤進行響應。

5.png

數據幀

7.2.2 標頭HEADERS 幀(type=0x01) 用於攜帶使用QPACK 編碼的HTTP 字段部分。

6.png

標頭幀

HEADERS 幀只能在請求流或push stream上發送。如果在控制流上接收到HEADERS 幀,則接收者必須以H3_FRAME_UNEXPECTED 類型的連接錯誤進行響應。

7.2.3 CANCEL_PUSHCANCEL_PUSH 幀(類型=0x03)用於在接收push stream之前請求取消服務器推送。 CANCEL_PUSH 幀通過推送ID(參見第4.6 節)標識服務器推送,編碼為可變長度整數。

當客戶端發送一個CANCEL_PUSH幀時,它表示不希望接收承諾的資源。服務器應該中止發送資源,但是這樣做的機制取決於相應的push stream的狀態。如果服務器還沒有創建push stream,它就不會創建push stream。如果push stream是打開的,服務器應該突然終止該流。如果push stream已經結束,服務器仍然可以突然終止流或不採取任何行動。

服務器發送一個CANCEL_PUSH幀來表明它不會履行先前發送的承諾。客戶端不能期望相應的承諾得到實現,除非它已經接收並處理了承諾的響應。無論是否打開了push stream,當服務器確定承諾不會被履行時,它應該發送一個CANCEL_PUSH 幀。如果流已經打開,服務器可以中止在流上發送,錯誤代碼為H3_REQUEST_CANCELLED。

發送CANCEL_PUSH 幀對現有push stream的狀態沒有直接影響。當客戶端已經接收到相應的push stream時,它不應該發送CANCEL_PUSH 幀。在客戶端發送CANCEL_PUSH 幀後,push stream可能會到達,因為服務器可能尚未處理CANCEL_PUSH。客戶端應該中止讀取流,錯誤代碼為H3_REQUEST_CANCELLED。

在控制流上發送CANCEL_PUSH 幀。在控制流以外的流上接收CANCEL_PUSH 幀必須被視為H3_FRAME_UNEXPECTED 類型的連接錯誤。

7.png

CANCEL_PUSH幀

CANCEL_PUSH 幀攜帶一個編碼為可變長度整數的Push ID。 Push ID字段標識正在被取消的服務器推送。如果接收到的CANCEL_PUSH幀引用了一個大於當前連接允許的push ID,這必須作為H3_ID_ERROR類型的連接錯誤處理。

如果客戶端收到CANCEL_PUSH 幀,則該幀可能會標識由於重新排序而尚未被PUSH_PROMISE 幀提及的推送ID。如果服務器接收到一個尚未被PUSH_PROMISE 幀提及的推送ID 的CANCEL_PUSH 幀,則必須將其視為H3_ID_ERROR 類型的連接錯誤。

7.2.4 設置SETTINGS 幀(type=0x04) 傳遞影響終端通信方式的配置參數,例如對對等行為的偏好和約束。單獨地,一個SETTINGS 參數也可以稱為'setting';每個SETTINGS參數的標識和值可以稱為“設置標識”和“設置值”。

SETTINGS 幀始終適用於整個HTTP/3 連接,而不是單個流。 SETTINGS 幀必須作為每個控制流的第一幀被每個對等方發送,並且不得隨後發送。如果終端在控制流上接收到第二個SETTINGS 幀,終端必須以H3_FRAME_UNEXPECTED 類型的連接錯誤響應。

SETTINGS 幀不得在控制流以外的任何流上發送。如果終端在不同的流上接收到SETTINGS 幀,終端必須以H3_FRAME_UNEXPECTED 類型的連接錯誤響應。

SETTINGS 參數未協商;它們描述了接收對等方可以使用的發送對等方的特徵。但是,使用SETTINGS 可以暗示協商:每個對等方都使用SETTINGS 來發布一組支持的值。設置的定義將描述每個對等方如何組合這兩個集合以得出將使用哪個選項的結論。 SETTINGS 不提供識別選擇何時生效的機制。

每個對等方可以通告相同參數的不同值。例如,客戶端可能願意使用非常大的響應字段段,而服務器則對請求大小更加謹慎。

相同的設置標識符不能在SETTINGS 幀中出現多次。接收端可以將重複設置標識符的存在視為H3_SETTINGS_ERROR類型的連接錯誤。

SETTINGS幀的有效載荷由零個或多個參數組成。每個參數由一個設置標識符和一個值組成,它們都編碼為QUIC可變長度整數。

8.png

設置幀

一個實現必須忽略任何帶有它不理解的標識符的參數。

7.2.4.1 定義SETTINGS參數HTTP/3 中定義了以下設置:

SETTINGS_MAX_FIELD_SECTION_SIZE (0x06):

默認值為無限制。

為N 的非負整數值設置格式為0x1f * N +0x21 的標識符被保留以執行忽略未知標識符的要求。此類設置沒有明確的含義。終端應該在其SETTINGS幀中包含至少一個這樣的設置。終端絕對不能認為這些設置在接收時有任何意義。

由於該設置沒有定義的含義,因此該設置的值可以是實現選擇的任何值。

在[HTTP/2]中定義的設置標識符沒有對應的HTTP/3設置也被保留。這些保留的設置絕對不能發送,並且它們的接收必須作為H3_SETTINGS_ERROR類型的連接錯誤處理。

其他設置可以通過HTTP/3 的擴展來定義。

7.2.4.2 初始化HTTP實現絕對不能發送基於當前對對等方設置的理解而無效的幀或請求。

所有設置都從初始值開始。每個終端應該使用這些初始值在對等方的SETTINGS幀到達之前發送消息,因為攜帶設置的數據包可能會丟失或延遲。當SETTINGS幀到達時,任何設置都將被更改為新的值。

這樣就不需要在發送消息之前等待SETTINGS幀。在發送SETTINGS幀之前,終端絕對不能要求從對等方接收任何數據,必須在傳輸準備好發送數據後立即發送設置。

對於服務器,每個客戶端設置的初始值都是默認值。

對於使用1-RTT QUIC連接的客戶端,每個服務器設置的初始值都是缺省值。 1-RTT項在包含設置的包被QUIC處理之前總是可用的,即使服務器立即發送SETTINGS 也是如此。客戶端不應該在發送請求之前無限期地等待SETTINGS 到達,但他們應該處理接收到的數據報以增加在發送第一個請求之前處理SETTINGS 的可能性。

當使用0-RTT QUIC連接時,每個服務器設置的初始值都是上一個會話中使用的值。客戶端應該存儲服務器在HTTP/3連接中提供的恢復信息的設置,但在某些情況下,他們可以選擇不存儲設置(例如,如果會話票據在SETTINGS幀之前收到)。當嘗試0-RTT時,客戶端必須遵守存儲的設置,如果沒有存儲值,則使用默認值。一旦服務器提供了新的設置,客戶端必須遵守這些值。

服務器可以記住它發布的設置,或存儲票據中值的完整性保護副本,並在接受0-RTT數據時恢復信息。服務器使用HTTP/3設置值來決定是否接受0-RTT數據。如果服務器不能確定客戶端記住的設置與它的當前設置是兼容的,它絕對不能接受0-RTT數據。如果符合這些設置的客戶端不會違反服務器的當前設置,則記住的設置是兼容的。

服務器可以接受0-RTT並隨後在其SETTINGS幀中提供不同的設置。如果0-RTT數據被服務器接受,它的SETTINGS幀絕對不能減少任何限製或改變任何可能被客戶端與它的0-RTT數據違反的值。服務器必須包括與其默認值不同的所有設置。如果服務器接受0-RTT,但隨後發送的設置與之前指定的設置不兼容,則必須將其視為H3_SETTINGS_ERROR 類型的連接錯誤。如果服務器接受0-RTT 但隨後發送的SETTINGS 幀忽略了客戶端理解的設置值(除了保留的設置標識符),該設置值之前指定為具有非默認值,則必須將其視為連接錯誤輸入H3_SETTINGS_ERROR。

7.2.5 PUSH_PROMISEPUSH_PROMISE 幀(類型=0x05)用於在請求流中從服務器到客戶端攜帶承諾的請求標頭部分。

8.png

PUSH_PROMISE 幀

有效載荷包括:

PUSHID:一個可變長度的整數,用於標識服務器推送操作。 Push ID用於push stream標頭和CANCEL_PUSH幀。

服務器絕對不能使用比客戶端提供的MAX_PUSH_ID幀大的Push ID。客戶端收到推送承諾幀時,如果推送承諾幀的ID大於客戶端發布的Push ID,則必須將其視為連接錯誤H3_ID_ERROR。

一個服務器可以在多個推送承諾幀中使用相同的Push ID。如果是這樣,解壓後的請求標頭集必須包含相同順序相同的字段,並且每個字段的名稱和值必須完全匹配。客戶端應該多次比較請求標頭部分以獲得承諾的資源。如果客戶端收到一個已經承諾的Push ID,並且檢測到不匹配,它必須響應一個H3_GENERAL_PROTOCOL_ERROR類型的連接錯誤。如果解壓後的字段部分完全匹配,客戶端應該將推送內容與每一個接收到推送承諾幀的流關聯起來。

允許重複引用相同的Push ID主要是為了減少並發請求造成的重複。服務器應該避免長時間重複使用Push ID。客戶端很可能使用服務器推送響應,而不保留它們以供重用。當客戶端看到一個推送承諾幀使用了一個他們已經使用並刪除的Push ID時,會被迫忽略這個承諾。

如果在控制流上接收到推送承諾幀,客戶端必須響應一個H3_FRAME_UNEXPECTED類型的連接錯誤。

客戶端不能發送PUSH_PROMISE幀。服務器必須將接收到的PUSH_PROMISE幀作為H3_FRAME_UNEXPECTED類型的連接錯誤處理。

關於整個服務器推送機制的描述,請參見4.6節。

7.2.6 關閉GOAWAY幀(type=0x07)用於啟動HTTP/3連接的任意終端的安全關閉。 GOAWAY 允許終端停止接受新請求或推送,同時仍完成對先前接收到的請求和推送的處理。這將啟用管理操作,例如服務器維護。 GOAWAY 本身不會關閉連接。

9.png

GOAWAY幀

GOAWAY幀總是在控制流上發送。在服務器到客戶端的方向上,它攜帶客戶端發起的雙向流的QUIC 流ID,編碼為可變長度整數。客戶端必須將接收到包含任何其他類型的流ID 的GOAWAY 幀視為H3_ID_ERROR 類型的連接錯誤。

在客戶端到服務器的方向上,GOAWAY幀攜帶一個被編碼為變長整數的Push ID。

GOAWAY幀適用於整個連接,而不是特定的流。客戶端必須將控制流以外的流上的GOAWAY幀作為H3_FRAME_UNEXPECTED類型的連接錯誤處理。

關於GOAWAY幀的更多信息請參見5.2節。

7.2.7 MAX_PUSH_IDMAX_PUSH_ID幀(type=0x0d)被客戶端用來控制服務器可以發起的服務器推送的數量。這設置了服務器可以在PUSH_PROMISE和CANCEL_PUSH幀中使用的Push ID的最大值。因此,除了由QUIC傳輸維持的限制外,這也限制了服務器可以發起的push stream的數量。

MAX_PUSH_ID幀總是在控制流上發送。在任何其他流上接收到MAX_PUSH_ID幀必須作為H3_FRAME_UNEXPECTED類型的連接

0 Comments

Recommended Comments

There are no comments to display.

Guest
Add a comment...