国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【譯】WebSocket協議第五章——數據幀(Data Framing)

Yujiaao / 3240人閱讀

摘要:數據幀協議正文概覽在協議中,數據是通過一系列數據幀來進行傳輸的。注意無論協議是否使用了,幀都需要添加掩碼。服務端收到沒有添加掩碼的數據幀以后,必須立即關閉連接。服務端禁止在發送數據幀給客戶端時添加掩碼。

概述

本文為WebSocket協議的第五章,本文翻譯的主要內容為WebSocket傳輸的數據相關內容。

數據幀(協議正文) 5.1 概覽

在WebSocket協議中,數據是通過一系列數據幀來進行傳輸的。為了避免由于網絡中介(例如一些攔截代理)或者一些在第10.3節討論的安全原因,客戶端必須在它發送到服務器的所有幀中添加掩碼(Mask)(具體細節見5.3節)。(注意:無論WebSocket協議是否使用了TLS,幀都需要添加掩碼)。服務端收到沒有添加掩碼的數據幀以后,必須立即關閉連接。在這種情況下,服務端可以發送一個在7.4.1節定義的狀態碼為1002(協議錯誤)的關閉幀。服務端禁止在發送數據幀給客戶端時添加掩碼。客戶端如果收到了一個添加了掩碼的幀,必須立即關閉連接。在這種情況下,它可以使用第7.4.1節定義的1002(協議錯誤)狀態碼。(這些規則可能會在將來的規范中放開)。

基礎的數據幀協議使用操作碼、有效負載長度和在“有效負載數據”中定義的放置“擴展數據”與“引用數據”的指定位置來定義幀類型。特定的bit位和操作碼為將來的協議擴展做了保留。

一個數據幀可以在開始握手完成之后和終端發送了一個關閉幀之前的任意一個時間通過客戶端或者服務端進行傳輸(第5.5.1節)。

5.2 基礎幀協議

在這節中的這種數據傳輸部分的有線格式是通過ABNFRFC5234來進行詳細說明的。(注意:不像這篇文檔中的其他章節內容,在這節中的ABNF是對bit組進行操作。每一個bit組的長度是在評論中展示的。在線上編碼時,最高位的bit是在ABNF最左邊的)。對于數據幀的高級的預覽可以見下圖。如果下圖指定的內容和這一節中后面的ABNF指定的內容有沖突的話,以下圖為準。

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length continued, if payload len == 127  |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
     |                     Payload Data continued ...                |
     +---------------------------------------------------------------+

FIN: 1 bit

? 表示這是消息的最后一個片段。第一個片段也有可能是最后一個片段。

RSV1,RSV2,RSV3: 每個1 bit

? 必須設置為0,除非擴展了非0值含義的擴展。如果收到了一個非0值但是沒有擴展任何非0值的含義,接收終端必須斷開WebSocket連接。

Opcode: 4 bit

? 定義“有效負載數據”的解釋。如果收到一個未知的操作碼,接收終端必須斷開WebSocket連接。下面的值是被定義過的。

? %x0 表示一個持續幀

? %x1 表示一個文本幀

? %x2 表示一個二進制幀

? %x3-7 預留給以后的非控制幀

? %x8 表示一個連接關閉包

? %x9 表示一個ping包

? %xA 表示一個pong包

? %xB-F 預留給以后的控制幀

Mask: 1 bit

? mask標志位,定義“有效負載數據”是否添加掩碼。如果設置為1,那么掩碼的鍵值存在于Masking-Key中,根據5.3節描述,這個一般用于解碼“有效負載數據”。所有的從客戶端發送到服務端的幀都需要設置這個bit位為1。

Payload length: 7 bits, 7+16 bits, or 7+64 bits

? 以字節為單位的“有效負載數據”長度,如果值為0-125,那么就表示負載數據的長度。如果是126,那么接下來的2個bytes解釋為16bit的無符號整形作為負載數據的長度。如果是127,那么接下來的8個bytes解釋為一個64bit的無符號整形(最高位的bit必須為0)作為負載數據的長度。多字節長度量以網絡字節順序表示(譯注:應該是指大端序和小端序)。在所有的示例中,長度值必須使用最小字節數來進行編碼,例如:長度為124字節的字符串不可用使用序列126,0,124進行編碼。有效負載長度是指“擴展數據”+“應用數據”的長度。“擴展數據”的長度可能為0,那么有效負載長度就是“應用數據”的長度。

Masking-Key: 0 or 4 bytes

? 所有從客戶端發往服務端的數據幀都已經與一個包含在這一幀中的32 bit的掩碼進行過了運算。如果mask標志位(1 bit)為1,那么這個字段存在,如果標志位為0,那么這個字段不存在。在5.3節中會介紹更多關于客戶端到服務端增加掩碼的信息。

Payload data: (x+y) bytes

? “有效負載數據”是指“擴展數據”和“應用數據”。

Extension data: x bytes

? 除非協商過擴展,否則“擴展數據”長度為0 bytes。在握手協議中,任何擴展都必須指定“擴展數據”的長度,這個長度如何進行計算,以及這個擴展如何使用。如果存在擴展,那么這個“擴展數據”包含在總的有效負載長度中。

Application data: y bytes

? 任意的“應用數據”,占用“擴展數據”后面的剩余所有字段。“應用數據”的長度等于有效負載長度減去“擴展應用”長度。

基礎數據幀協議通過ABNF進行了正式的定義。需要重點知道的是,這些數據都是二進制的,而不是ASCII字符。例如,長度為1 bit的字段的值為%x0 / %x1代表的是一個值為0/1的多帶帶的bit,而不是一整個字節(8 bit)來代表ASCII編碼的字符“0”和“1”。一個長度為4 bit的范圍是%x0-F的字段值代表的是4個bit,而不是字節(8 bit)對應的ASCII碼的值。不要指定字符編碼:“規則解析為一組最終的值,有時候是字符。在ABNF中,字符僅僅是一個非負的數字。在特定的上下文中,會根據特定的值的映射(編碼)編碼集(例如ASCII)”。在這里,指定的編碼類型是將每個字段編碼為特定的bits數組的二進制編碼的最終數據。

ws-frame =

frame-fin; 長度為1 bit

frame-rsv1; 長度為1 bit

frame-rsv2; 長度為1 bit

frame-rsv3; 長度為1 bit

frame-opcode; 長度為4 bit

frame-masked; 長度為1 bit

frame-payload-length; 長度為7或者7+16或者7+64 bit

[frame-masking-key]; 長度為32 bit

frame-payload-data; 長度為大于0的n*8 bit(其中n>0)

frame-fin =

%x0,除了以下為1的情況

%x1,最后一個消息幀

長度為1 bit

frame-rsv1 =

%x0 / %x1,長度為1 bit,如果沒有協商則必須為0

frame-rsv2 =

%x0 / %x1,長度為1 bit,如果沒有協商則必須為0

frame-rsv3 =

%x0 / %x1,長度為1 bit,如果沒有協商則必須為0

frame-opcode =

frame-opcode-non-control

frame-opcode-control

frame-opcode-cont

frame-opcode-non-control

%x1,文本幀

%x2,二進制幀

%x3-7,保留給將來的非控制幀

長度為4 bit

frame-opcode-control

%x8,連接關閉

%x9,ping幀

%xA,pong幀

%xB-F,保留給將來的控制幀

長度為4 bit

frame-masked

%x0,不添加掩碼,沒有frame-masking-key

%x1,添加掩碼,存在frame-masking-key

長度為1 bit

frame-payload-length

%x00-7D,長度為7 bit

%x7E frame-payload-length-16,長度為7+16 bit

%x7F frame-payload-length-63,長度為7+64 bit

frame-payload-length-16

%x0000-FFFF,長度為16 bit

frame-payload-length-63

%x0000000000000000-7FFFFFFFFFFFFFFF,長度為64 bit

frame-masking-key

4(%x00-FF),當frame-mask為1時存在,長度為32 bit

frame-payload-data

frame-masked-extension-data frame-masked-application-data,當frame-masked為1時

frame-unmasked-extension-data frame-unmasked-application-data,當frame-masked為0時

frame-masked-extension-data

*(%x00-FF),保留給將來的擴展,長度為n*8,其中n>0

frame-masked-application-data

*(%x00-FF),長度為n*8,其中n>0

frame-unmasked-extension-data

*(%x00-FF),保留給將來的擴展,長度為n*8,其中n>0

frame-unmasked-application-data

*(%x00-FF),長度為n*8,其中n>0

5.3 客戶端到服務端添加掩碼

添加掩碼的數據幀必須像5.2節定義的一樣,設置frame-masked字段為1。

掩碼值像第5.2節說到的完全包含在幀中的frame-masking-key上。它是用于對定義在同一節中定義的幀負載數據Payload data字段中的包含Extension dataApplication data的數據進行添加掩碼。

掩碼字段是一個由客戶端隨機選擇的32bit的值。當準備掩碼幀時,客戶端必須從允許的32bit值中須知你咋一個新的掩碼值。掩碼值必須是不可被預測的;因此,掩碼必須來自強大的熵源(entropy),并且給定的掩碼不能讓服務器或者代理能夠很容易的預測到后續幀。掩碼的不可預測性對于預防惡意應用作者在網上暴露相關的字節數據至關重要。RFC 4086討論了安全敏感的應用需要一個什么樣的合適的強大的熵源。

掩碼不影響Payload data的長度。進行掩碼的數據轉換為非掩碼數據,或者反過來,根據下面的算法即可。這個同樣的算法適用于任意操作方向的轉換,例如:對數據進行掩碼操作和對數據進行反掩碼操作所涉及的步驟是相同的。

表示轉換后數據的八位字節的i(transformed-octet-i?)是表示的原始數據的i(original-octet-i)與索引i模4得到的掩碼值(masking-key-octet-j)經過異或操作(XOR)得到的:

j = i MOD 4
transfromed-octed-i = original-octet-i XOR masking-key-octet-j

在規范中定義的位于frame-payload-length字段的有效負載的長度,不包括掩碼值的長度。它只是Payload data的長度。如跟在掩碼值后面的字節數組的數。

5.4 消息分片

消息分片的主要目的是允許發送一個未知長度且消息開始發送后不需要緩存的消息。如果消息不能被分片,那么一端必須在緩存整個消息,因此這個消息的長度必須在第一個字節發送前就需要計算出來。如果有消息分片,服務端或者代理可以選擇一個合理的緩存長度,當緩存區滿了以后,就想網絡發送一個片段。

第二個消息分片使用的場景是不適合在一個邏輯通道內傳輸一個大的消息占滿整個輸出頻道的多路復用場景。多路復用需要能夠將消息進行自由的切割成更小的片段來共享輸出頻道。(注意:多路復用的擴展不在這個文檔中討論)。

除非在擴展中另有規定,否則幀沒有語義的含義。如果客戶端和服務的沒有協商擴展字段,或者服務端和客戶端協商了一些擴展字段,并且代理能夠完全識別所有的協商擴展字段,在這些擴展字段存在的情況下知道如何進行幀的合并和拆分,代理就可能會合并或者拆分幀。這個的一個含義是指在缺少擴展字段的情況下,發送者和接收者都不能依賴特定的幀邊界的存在。

消息分片相關的規則如下:

一個未分片的消息包含一個設置了FIN字段(標記為1)的多帶帶的幀和一個除0以外的操作碼。

一個分片的消息包含一個未設置的FIN字段(標記為0)的多帶帶的幀和一個除0以外的操作碼,然后跟著0個或者多個未設置FIN字段的幀和操作碼為0的幀,然后以一個設置了FIN字段以及操作碼為0的幀結束。一個分片的消息內容按幀順序組合后的payload字段,是等價于一個多帶帶的更大的消息payload字段中包含的值;然而,如果擴展字段存在,因為擴展字段定義了Extension data的解析方式,因此前面的結論可能不成立。例如:Extension data可能只出現在第一個片段的開頭,并適用于接下來的片段,或者可能每一個片段都有Extension data,但是只適用于特定的片段。在Extension data不存在時,下面的示例演示了消息分片是如何運作的。
示例:一個文本需要分成三個片段進行發送,第一個片段包含的操作碼為0x1并且未設置FIN字段,第二個片段的操作碼為0x0并且未設置FIN字段,第三個片段的操作碼為0x0并且設置了FIN字段。

控制幀(見5.5節)可能被插入到分片消息的中間。控制幀不能被分片。

消息片段必須在發送端按照順序發送給接收端。

除非在擴展中定義了這種嵌套的邏輯,否則一條消息分的片不能與另一條消息分的片嵌套傳輸。

終端必須有能力來處理在分片的消息中的控制幀。

發送端可能會創建任意大小的非控制消息片段。

客戶端和服務端必須同時支持分片和不分片消息。

控制幀不能被分片,并且代理不允許改變控制幀的片段。

如果有保留字段被使用并且代理不能理解這些字段的值時,那么代理不能改變消息的片段。

在擴展字段已經被協商過,但是代理不知道協商擴展字段的具體語義時,代理不能改變任意消息的片段。同樣的,擴展不能看到WebSocket握手(并且得不到通知內容)導致WebSocket的連接禁止改變連接過程中任意的消息片段。

作為這些規則的結論,所有的消息片段都是同類型的,并且設置了第一個片段的操作碼(opccode)字段。控制幀不能被分片,所有的消息分片類型必須是文本或者二進制,或者是保留的任意一個操作碼。

注:如果控制幀沒有被打斷,心跳(ping)的等待時間可能會變很長,例如在一個很大的消息之后。因此,在分片的消息傳輸中插入控制幀是有必要的。

實踐說明:如果擴展字段不存在,接收者不需要使用緩存來存儲下整個消息片段來進行處理。例如:如果使用一個流式API,再收到部分幀的時候就可以將數據交給上層應用。然而,這個假設對以后所有的WebSocket擴展可能不一定成立。

5.5 控制幀

控制幀是通過操作碼最高位的值為1來進行區分的。當前已經定義的控制幀操作碼包括0x8(關閉),0x9(心跳Ping)和0xA(心跳Pong)。操作碼0xB-0xF沒有被定義,當前被保留下來做為以后的控制幀。

控制幀是用于WebSocket的通信狀態的。控制幀可以被插入到消息片段中進行傳輸。

所有的控制幀必須有一個126字節或者更小的負載長度,并且不能被分片。

5.5.1 關閉(Close)

控制幀的操作碼值是0x8。

關閉幀可能包含內容(body)(幀的“應用數據”部分)來表明連接關閉的原因,例如終端的斷開,或者是終端收到了一個太大的幀,或者是終端收到了一個不符合預期的格式的內容。如果這個內容存在,內容的前兩個字節必須是一個無符號整型(按照網絡字節序)來代表在7.4節中定義的狀態碼。跟在這兩個整型字節之后的可以是UTF-8編碼的的數據值(原因),數據值的定義不在此文檔中。數據值不一定是要人可以讀懂的,但是必須對于調試有幫助,或者能傳遞有關于當前打開的這條連接有關聯的信息。數據值不保證人一定可以讀懂,所以不能把這些展示給終端用戶。

從客戶端發送給服務端的控制幀必須添加掩碼,具體見5.3節。

應用禁止在發送了關閉的控制幀后再發送任何的數據幀。

如果終端收到了一個關閉的控制幀并且沒有在以前發送一個關閉幀,那么終端必須發送一個關閉幀作為回應。(當發送一個關閉幀作為回應時,終端通常會輸出它收到的狀態碼)響應的關閉幀應該盡快發送。終端可能會推遲發送關閉幀直到當前的消息都已經發送完成(例如:如果大多數分片的消息已經發送了,終端可能會在發送關閉幀之前將剩余的消息片段發送出去)。然而,已經發送關閉幀的終端不能保證會繼續處理收到的消息。

在已經發送和收到了關閉幀后,終端認為WebSocket連接以及關閉了,并且必須關閉底層的TCP連接。服務端必須馬上關閉底層的TCP連接,客戶端應該等待服務端關閉連接,但是也可以在收到關閉幀以后任意時間關閉連接。例如:如果在合理的時間段內沒有收到TCP關閉指令。

如果客戶端和服務端咋同一個時間發送了關閉幀,兩個終端都會發送和接收到一條關閉的消息,并且應該認為WebSocket連接已經關閉,同時關閉底層的TCP連接。

5.5.2 心跳Ping

心跳Ping幀包含的操作碼是0x9。

關閉幀可能包含“應用數據”。

如果收到了一個心跳Ping幀,那么終端必須發送一個心跳Pong 幀作為回應,除非已經收到了一個關閉幀。終端應該盡快恢復Pong幀。Pong幀將會在5.5.3節討論。

終端可能會在建立連接后與連接關閉前中間的任意時間發送Ping幀。

注意:Ping幀可能是用于保活或者用來驗證遠端是否仍然有應答。

5.5.3 心跳Pong

心跳Ping幀包含的操作碼是0xA。

5.5.2節詳細說明了Ping幀和Pong幀的要求。

作為回應發送的Pong幀必須完整攜帶Ping幀中傳遞過來的“應用數據”字段。

如果終端收到一個Ping幀但是沒有發送Pong幀來回應之前的pong幀,那么終端可能選擇用Pong幀來回復最近處理的那個Ping幀。

Pong幀可以被主動發送。這會作為一個單項的心跳。預期外的Pong包的響應沒有規定。

5.6 數據幀

數據幀(例如非控制幀)的定義是操作碼的最高位值為0。當前定義的數據幀操作嗎包含0x1(文本)、0x2(二進制)。操作碼0x3-0x7是被保留作為非控制幀的操作碼。

數據幀會攜帶應用層/擴展層數據。操作碼決定了攜帶的數據解析方式:

文本

“負載字段”是用UTF-8編碼的文本數據。注意特殊的文本幀可能包含部分UTF-8序列;然而,整個消息必須是有效的UTF-8編碼數據。重新組合消息后無效的UTF-8編碼數據處理見8.1節。

二進制

“負載字段”是任意的二進制數據,二進制數據的解析僅僅依靠應用層。

5.7 示例

一個單幀未添加掩碼的文本消息
0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f (內容為"Hello")

一個單幀添加掩碼的文本消息
0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58 (內容為Hello")

一個分片的未添加掩碼的文本消息
0x01 0x03 0x48 0x65 0x6c (內容為"Hel")
0x80 0x02 0x6c 0x6f (內容為”lo")

未添加掩碼的Ping請求和添加掩碼的Ping響應(譯者注:即Pong)
0x89 0x05 0x48 0x65 0x6c 0x6c 0x6f (包含內容為”Hello", 但是文本內容是任意的)
0x8a 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58 (包含內容為”Hello", 匹配ping的內容)

256字節的二進制數據放入一個未添加掩碼數據幀
0x82 0x7E 0x0100 [256 bytes of binary data]

64KB二進制數據在一個非掩碼幀中
0x82 0x7F 0x0000000000010000 [65536 bytes of binary data]

5.8 擴展性

這個協議的設計初衷是允許擴展的,可以在基礎協議上增加能力。終端的連接必須在握手的過程中協商使用的所有擴展。在規范中提供了從0x3-0x7和0xB-0xF的操作碼,在數據幀Header中的“擴展數據”字段、frame-rsv1、frame-rsv2、frame-rsv3字段都可以用于擴展。擴展的協商討論將在以后的9.1節中詳細討論。下面是一些符合預期的擴展用法。下面的列表不完整,也不是規范中內容。

“擴展數據”可以放置在“負載數據“中的應用數據”之前的位置。

保留的字段可以在每一幀需要時被使用。

保留的操作碼的值可以被定義。

如果需要更多的操作碼,那么保留的操作碼字段可以被定義。

保留的字段或者“擴展”操作碼可以在“負載數據”之中的分配額外的位置來定義,這樣可以定義更大的操作碼或者更多的每一幀的字段。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/101884.html

相關文章

  • WebSocket協議五章——數據(Data Framing)

    摘要:概述本文為協議的第五章,本文翻譯的主要內容為傳輸的數據相關內容。注意無論協議是否使用了,幀都需要添加掩碼。服務端收到沒有添加掩碼的數據幀以后,必須立即關閉連接。服務端禁止在發送數據幀給客戶端時添加掩碼。基礎數據幀協議通過進行了正式的定義。 概述 本文為WebSocket協議的第五章,本文翻譯的主要內容為WebSocket傳輸的數據相關內容。 有興趣了解該文檔之前幾張內容的同學可以見: ...

    nevermind 評論0 收藏0
  • WebSocket 協議 RFC 文檔(全中文翻

    摘要:概述經過半年的搗鼓,終于將協議全篇翻譯完成。現在將所有章節全部整理到一篇文章中,方便大家閱讀。如果大家想看具體的翻譯文檔,可以去我的中查看。大家有相關類型的需要,建議大家可以嘗試下。 概述 經過半年的搗鼓,終于將 WebSocket 協議(RFC6455)全篇翻譯完成。現在將所有章節全部整理到一篇文章中,方便大家閱讀。如果大家想看具體的翻譯文檔,可以去我的GitHub中查看。 具體章節...

    ghnor 評論0 收藏0
  • Node.js - 200 多行代碼實現 Websocket 協議

    摘要:預備工作序最近正在研究相關的知識,想著如何能自己實現協議。監聽事件就是協議的抽象,直接在上面監聽已有的事件和事件這兩個事件。表示當前數據幀為消息的最后一個數據幀,此時接收方已經收到完整的消息,可以對消息進行處理。 A、預備工作 1、序 最近正在研究 Websocket 相關的知識,想著如何能自己實現 Websocket 協議。到網上搜羅了一番資料后用 Node.js 實現該協議,倒也沒...

    張巨偉 評論0 收藏0
  • 用 Node 實現簡單 WebSocket 協議

    摘要:用實現簡單協議從瀏覽器說起瀏覽器提供的非常簡潔。創建連接連接建立時的回調收到消息時的回調連接出錯時的回調連接終止時的回調發送消息告訴我們也就是說,在創建對象時,瀏覽器嘗試與服務端建立連接發送請求建立個服務端一旦收到數據,就會觸發。 用 Node 實現簡單 WebSocket 協議 從瀏覽器 WebSocket API 說起 瀏覽器提供的 WebSocket API 非常簡潔。 let...

    chavesgu 評論0 收藏0
  • JavaScript 工作原理之五-深入理解 WebSockets 和帶有 SSE 機制的HTTP/

    摘要:幀協議讓我們深入了解下幀協議。目前可用的值該幀接續前面一幀的有效載荷。該幀包含二進制數據。幀有以下幾類長度表示有效載荷的長度。數據分片有效載荷數據可以被分成多個獨立的幀。接收端會緩沖這些幀直到位有值。 原文請查閱這里,略有改動,本文采用知識共享署名 3.0 中國大陸許可協議共享,BY Troland。 本系列持續更新中,Github 地址請查閱這里。 這是 JavaScript 工作原...

    lijinke666 評論0 收藏0

發表評論

0條評論

Yujiaao

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<