摘要:概述本文為協(xié)議的第五章,本文翻譯的主要內(nèi)容為傳輸?shù)臄?shù)據(jù)相關(guān)內(nèi)容。注意無論協(xié)議是否使用了,幀都需要添加掩碼。服務(wù)端收到?jīng)]有添加掩碼的數(shù)據(jù)幀以后,必須立即關(guān)閉連接。服務(wù)端禁止在發(fā)送數(shù)據(jù)幀給客戶端時添加掩碼。基礎(chǔ)數(shù)據(jù)幀協(xié)議通過進行了正式的定義。
概述
本文為WebSocket協(xié)議的第五章,本文翻譯的主要內(nèi)容為WebSocket傳輸?shù)臄?shù)據(jù)相關(guān)內(nèi)容。
有興趣了解該文檔之前幾張內(nèi)容的同學(xué)可以見:
【譯】WebSocket協(xié)議第一章——介紹(Introduction)
【譯】WebSocket協(xié)議第二章——一致性要求(Conformance Requirements)
【譯】WebSocket協(xié)議第三章——WebSocket網(wǎng)址(WebSocket URIs)
【譯】WebSocket協(xié)議第四章——連接握手(Opening Handshake)
數(shù)據(jù)幀(協(xié)議正文) 5.1 概覽在WebSocket協(xié)議中,數(shù)據(jù)是通過一系列數(shù)據(jù)幀來進行傳輸?shù)?。為了避免由于網(wǎng)絡(luò)中介(例如一些攔截代理)或者一些在第10.3節(jié)討論的安全原因,客戶端必須在它發(fā)送到服務(wù)器的所有幀中添加掩碼(Mask)(具體細節(jié)見5.3節(jié))。(注意:無論WebSocket協(xié)議是否使用了TLS,幀都需要添加掩碼)。服務(wù)端收到?jīng)]有添加掩碼的數(shù)據(jù)幀以后,必須立即關(guān)閉連接。在這種情況下,服務(wù)端可以發(fā)送一個在7.4.1節(jié)定義的狀態(tài)碼為1002(協(xié)議錯誤)的關(guān)閉幀。服務(wù)端禁止在發(fā)送數(shù)據(jù)幀給客戶端時添加掩碼??蛻舳巳绻盏搅艘粋€添加了掩碼的幀,必須立即關(guān)閉連接。在這種情況下,它可以使用第7.4.1節(jié)定義的1002(協(xié)議錯誤)狀態(tài)碼。(這些規(guī)則可能會在將來的規(guī)范中放開)。
基礎(chǔ)的數(shù)據(jù)幀協(xié)議使用操作碼、有效負載長度和在“有效負載數(shù)據(jù)”中定義的放置“擴展數(shù)據(jù)”與“引用數(shù)據(jù)”的指定位置來定義幀類型。特定的bit位和操作碼為將來的協(xié)議擴展做了保留。
一個數(shù)據(jù)幀可以在開始握手完成之后和終端發(fā)送了一個關(guān)閉幀之前的任意一個時間通過客戶端或者服務(wù)端進行傳輸(第5.5.1節(jié))。
5.2 基礎(chǔ)幀協(xié)議在這節(jié)中的這種數(shù)據(jù)傳輸部分的有線格式是通過ABNFRFC5234來進行詳細說明的。(注意:不像這篇文檔中的其他章節(jié)內(nèi)容,在這節(jié)中的ABNF是對bit組進行操作。每一個bit組的長度是在評論中展示的。在線上編碼時,最高位的bit是在ABNF最左邊的)。對于數(shù)據(jù)幀的高級的預(yù)覽可以見下圖。如果下圖指定的內(nèi)容和這一節(jié)中后面的ABNF指定的內(nèi)容有沖突的話,以下圖為準(zhǔn)。
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
? 必須設(shè)置為0,除非擴展了非0值含義的擴展。如果收到了一個非0值但是沒有擴展任何非0值的含義,接收終端必須斷開WebSocket連接。
Opcode: 4 bit
? 定義“有效負載數(shù)據(jù)”的解釋。如果收到一個未知的操作碼,接收終端必須斷開WebSocket連接。下面的值是被定義過的。
? %x0 表示一個持續(xù)幀
? %x1 表示一個文本幀
? %x2 表示一個二進制幀
? %x3-7 預(yù)留給以后的非控制幀
? %x8 表示一個連接關(guān)閉包
? %x9 表示一個ping包
? %xA 表示一個pong包
? %xB-F 預(yù)留給以后的控制幀
Mask: 1 bit
? mask標(biāo)志位,定義“有效負載數(shù)據(jù)”是否添加掩碼。如果設(shè)置為1,那么掩碼的鍵值存在于Masking-Key中,根據(jù)5.3節(jié)描述,這個一般用于解碼“有效負載數(shù)據(jù)”。所有的從客戶端發(fā)送到服務(wù)端的幀都需要設(shè)置這個bit位為1。
Payload length: 7 bits, 7+16 bits, or 7+64 bits
? 以字節(jié)為單位的“有效負載數(shù)據(jù)”長度,如果值為0-125,那么就表示負載數(shù)據(jù)的長度。如果是126,那么接下來的2個bytes解釋為16bit的無符號整形作為負載數(shù)據(jù)的長度。如果是127,那么接下來的8個bytes解釋為一個64bit的無符號整形(最高位的bit必須為0)作為負載數(shù)據(jù)的長度。多字節(jié)長度量以網(wǎng)絡(luò)字節(jié)順序表示(譯注:應(yīng)該是指大端序和小端序)。在所有的示例中,長度值必須使用最小字節(jié)數(shù)來進行編碼,例如:長度為124字節(jié)的字符串不可用使用序列126,0,124進行編碼。有效負載長度是指“擴展數(shù)據(jù)”+“應(yīng)用數(shù)據(jù)”的長度。“擴展數(shù)據(jù)”的長度可能為0,那么有效負載長度就是“應(yīng)用數(shù)據(jù)”的長度。
Masking-Key: 0 or 4 bytes
? 所有從客戶端發(fā)往服務(wù)端的數(shù)據(jù)幀都已經(jīng)與一個包含在這一幀中的32 bit的掩碼進行過了運算。如果mask標(biāo)志位(1 bit)為1,那么這個字段存在,如果標(biāo)志位為0,那么這個字段不存在。在5.3節(jié)中會介紹更多關(guān)于客戶端到服務(wù)端增加掩碼的信息。
Payload data: (x+y) bytes
? “有效負載數(shù)據(jù)”是指“擴展數(shù)據(jù)”和“應(yīng)用數(shù)據(jù)”。
Extension data: x bytes
? 除非協(xié)商過擴展,否則“擴展數(shù)據(jù)”長度為0 bytes。在握手協(xié)議中,任何擴展都必須指定“擴展數(shù)據(jù)”的長度,這個長度如何進行計算,以及這個擴展如何使用。如果存在擴展,那么這個“擴展數(shù)據(jù)”包含在總的有效負載長度中。
Application data: y bytes
? 任意的“應(yīng)用數(shù)據(jù)”,占用“擴展數(shù)據(jù)”后面的剩余所有字段。“應(yīng)用數(shù)據(jù)”的長度等于有效負載長度減去“擴展應(yīng)用”長度。
基礎(chǔ)數(shù)據(jù)幀協(xié)議通過ABNF進行了正式的定義。需要重點知道的是,這些數(shù)據(jù)都是二進制的,而不是ASCII字符。例如,長度為1 bit的字段的值為%x0 / %x1代表的是一個值為0/1的多帶帶的bit,而不是一整個字節(jié)(8 bit)來代表ASCII編碼的字符“0”和“1”。一個長度為4 bit的范圍是%x0-F的字段值代表的是4個bit,而不是字節(jié)(8 bit)對應(yīng)的ASCII碼的值。不要指定字符編碼:“規(guī)則解析為一組最終的值,有時候是字符。在ABNF中,字符僅僅是一個非負的數(shù)字。在特定的上下文中,會根據(jù)特定的值的映射(編碼)編碼集(例如ASCII)”。在這里,指定的編碼類型是將每個字段編碼為特定的bits數(shù)組的二進制編碼的最終數(shù)據(jù)。
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,如果沒有協(xié)商則必須為0
frame-rsv2 =
%x0 / %x1,長度為1 bit,如果沒有協(xié)商則必須為0
frame-rsv3 =
%x0 / %x1,長度為1 bit,如果沒有協(xié)商則必須為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,連接關(guān)閉
%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),當(dāng)frame-mask為1時存在,長度為32 bit
frame-payload-data
frame-masked-extension-data frame-masked-application-data,當(dāng)frame-masked為1時
frame-unmasked-extension-data frame-unmasked-application-data,當(dāng)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 客戶端到服務(wù)端添加掩碼添加掩碼的數(shù)據(jù)幀必須像5.2節(jié)定義的一樣,設(shè)置frame-masked字段為1。
掩碼值像第5.2節(jié)說到的完全包含在幀中的frame-masking-key上。它是用于對定義在同一節(jié)中定義的幀負載數(shù)據(jù)Payload data字段中的包含Extension data和Application data的數(shù)據(jù)進行添加掩碼。
掩碼字段是一個由客戶端隨機選擇的32bit的值。當(dāng)準(zhǔn)備掩碼幀時,客戶端必須從允許的32bit值中須知你咋一個新的掩碼值。掩碼值必須是不可被預(yù)測的;因此,掩碼必須來自強大的熵源(entropy),并且給定的掩碼不能讓服務(wù)器或者代理能夠很容易的預(yù)測到后續(xù)幀。掩碼的不可預(yù)測性對于預(yù)防惡意應(yīng)用作者在網(wǎng)上暴露相關(guān)的字節(jié)數(shù)據(jù)至關(guān)重要。RFC 4086討論了安全敏感的應(yīng)用需要一個什么樣的合適的強大的熵源。
掩碼不影響Payload data的長度。進行掩碼的數(shù)據(jù)轉(zhuǎn)換為非掩碼數(shù)據(jù),或者反過來,根據(jù)下面的算法即可。這個同樣的算法適用于任意操作方向的轉(zhuǎn)換,例如:對數(shù)據(jù)進行掩碼操作和對數(shù)據(jù)進行反掩碼操作所涉及的步驟是相同的。
表示轉(zhuǎn)換后數(shù)據(jù)的八位字節(jié)的i(transformed-octet-i?)是表示的原始數(shù)據(jù)的i(original-octet-i)與索引i模4得到的掩碼值(masking-key-octet-j)經(jīng)過異或操作(XOR)得到的:
j = i MOD 4
transfromed-octed-i = original-octet-i XOR masking-key-octet-j
在規(guī)范中定義的位于frame-payload-length字段的有效負載的長度,不包括掩碼值的長度。它只是Payload data的長度。如跟在掩碼值后面的字節(jié)數(shù)組的數(shù)。
5.4 消息分片消息分片的主要目的是允許發(fā)送一個未知長度且消息開始發(fā)送后不需要緩存的消息。如果消息不能被分片,那么一端必須在緩存整個消息,因此這個消息的長度必須在第一個字節(jié)發(fā)送前就需要計算出來。如果有消息分片,服務(wù)端或者代理可以選擇一個合理的緩存長度,當(dāng)緩存區(qū)滿了以后,就想網(wǎng)絡(luò)發(fā)送一個片段。
第二個消息分片使用的場景是不適合在一個邏輯通道內(nèi)傳輸一個大的消息占滿整個輸出頻道的多路復(fù)用場景。多路復(fù)用需要能夠?qū)⑾⑦M行自由的切割成更小的片段來共享輸出頻道。(注意:多路復(fù)用的擴展不在這個文檔中討論)。
除非在擴展中另有規(guī)定,否則幀沒有語義的含義。如果客戶端和服務(wù)的沒有協(xié)商擴展字段,或者服務(wù)端和客戶端協(xié)商了一些擴展字段,并且代理能夠完全識別所有的協(xié)商擴展字段,在這些擴展字段存在的情況下知道如何進行幀的合并和拆分,代理就可能會合并或者拆分幀。這個的一個含義是指在缺少擴展字段的情況下,發(fā)送者和接收者都不能依賴特定的幀邊界的存在。
消息分片相關(guān)的規(guī)則如下:
一個未分片的消息包含一個設(shè)置了FIN字段(標(biāo)記為1)的多帶帶的幀和一個除0以外的操作碼。
一個分片的消息包含一個未設(shè)置的FIN字段(標(biāo)記為0)的多帶帶的幀和一個除0以外的操作碼,然后跟著0個或者多個未設(shè)置FIN字段的幀和操作碼為0的幀,然后以一個設(shè)置了FIN字段以及操作碼為0的幀結(jié)束。一個分片的消息內(nèi)容按幀順序組合后的payload字段,是等價于一個多帶帶的更大的消息payload字段中包含的值;然而,如果擴展字段存在,因為擴展字段定義了Extension data的解析方式,因此前面的結(jié)論可能不成立。例如:Extension data可能只出現(xiàn)在第一個片段的開頭,并適用于接下來的片段,或者可能每一個片段都有Extension data,但是只適用于特定的片段。在Extension data不存在時,下面的示例演示了消息分片是如何運作的。
示例:一個文本需要分成三個片段進行發(fā)送,第一個片段包含的操作碼為0x1并且未設(shè)置FIN字段,第二個片段的操作碼為0x0并且未設(shè)置FIN字段,第三個片段的操作碼為0x0并且設(shè)置了FIN字段。
控制幀(見5.5節(jié))可能被插入到分片消息的中間??刂茙荒鼙环制?。
消息片段必須在發(fā)送端按照順序發(fā)送給接收端。
除非在擴展中定義了這種嵌套的邏輯,否則一條消息分的片不能與另一條消息分的片嵌套傳輸。
終端必須有能力來處理在分片的消息中的控制幀。
發(fā)送端可能會創(chuàng)建任意大小的非控制消息片段。
客戶端和服務(wù)端必須同時支持分片和不分片消息。
控制幀不能被分片,并且代理不允許改變控制幀的片段。
如果有保留字段被使用并且代理不能理解這些字段的值時,那么代理不能改變消息的片段。
在擴展字段已經(jīng)被協(xié)商過,但是代理不知道協(xié)商擴展字段的具體語義時,代理不能改變?nèi)我庀⒌钠?。同樣的,擴展不能看到WebSocket握手(并且得不到通知內(nèi)容)導(dǎo)致WebSocket的連接禁止改變連接過程中任意的消息片段。
作為這些規(guī)則的結(jié)論,所有的消息片段都是同類型的,并且設(shè)置了第一個片段的操作碼(opccode)字段??刂茙荒鼙环制械南⒎制愋捅仨毷俏谋净蛘叨M制,或者是保留的任意一個操作碼。
注:如果控制幀沒有被打斷,心跳(ping)的等待時間可能會變很長,例如在一個很大的消息之后。因此,在分片的消息傳輸中插入控制幀是有必要的。
實踐說明:如果擴展字段不存在,接收者不需要使用緩存來存儲下整個消息片段來進行處理。例如:如果使用一個流式API,再收到部分幀的時候就可以將數(shù)據(jù)交給上層應(yīng)用。然而,這個假設(shè)對以后所有的WebSocket擴展可能不一定成立。
5.5 控制幀控制幀是通過操作碼最高位的值為1來進行區(qū)分的。當(dāng)前已經(jīng)定義的控制幀操作碼包括0x8(關(guān)閉),0x9(心跳Ping)和0xA(心跳Pong)。操作碼0xB-0xF沒有被定義,當(dāng)前被保留下來做為以后的控制幀。
控制幀是用于WebSocket的通信狀態(tài)的??刂茙梢员徊迦氲较⑵沃羞M行傳輸。
所有的控制幀必須有一個126字節(jié)或者更小的負載長度,并且不能被分片。
5.5.1 關(guān)閉(Close)控制幀的操作碼值是0x8。
關(guān)閉幀可能包含內(nèi)容(body)(幀的“應(yīng)用數(shù)據(jù)”部分)來表明連接關(guān)閉的原因,例如終端的斷開,或者是終端收到了一個太大的幀,或者是終端收到了一個不符合預(yù)期的格式的內(nèi)容。如果這個內(nèi)容存在,內(nèi)容的前兩個字節(jié)必須是一個無符號整型(按照網(wǎng)絡(luò)字節(jié)序)來代表在7.4節(jié)中定義的狀態(tài)碼。跟在這兩個整型字節(jié)之后的可以是UTF-8編碼的的數(shù)據(jù)值(原因),數(shù)據(jù)值的定義不在此文檔中。數(shù)據(jù)值不一定是要人可以讀懂的,但是必須對于調(diào)試有幫助,或者能傳遞有關(guān)于當(dāng)前打開的這條連接有關(guān)聯(lián)的信息。數(shù)據(jù)值不保證人一定可以讀懂,所以不能把這些展示給終端用戶。
從客戶端發(fā)送給服務(wù)端的控制幀必須添加掩碼,具體見5.3節(jié)。
應(yīng)用禁止在發(fā)送了關(guān)閉的控制幀后再發(fā)送任何的數(shù)據(jù)幀。
如果終端收到了一個關(guān)閉的控制幀并且沒有在以前發(fā)送一個關(guān)閉幀,那么終端必須發(fā)送一個關(guān)閉幀作為回應(yīng)。(當(dāng)發(fā)送一個關(guān)閉幀作為回應(yīng)時,終端通常會輸出它收到的狀態(tài)碼)響應(yīng)的關(guān)閉幀應(yīng)該盡快發(fā)送。終端可能會推遲發(fā)送關(guān)閉幀直到當(dāng)前的消息都已經(jīng)發(fā)送完成(例如:如果大多數(shù)分片的消息已經(jīng)發(fā)送了,終端可能會在發(fā)送關(guān)閉幀之前將剩余的消息片段發(fā)送出去)。然而,已經(jīng)發(fā)送關(guān)閉幀的終端不能保證會繼續(xù)處理收到的消息。
在已經(jīng)發(fā)送和收到了關(guān)閉幀后,終端認為WebSocket連接以及關(guān)閉了,并且必須關(guān)閉底層的TCP連接。服務(wù)端必須馬上關(guān)閉底層的TCP連接,客戶端應(yīng)該等待服務(wù)端關(guān)閉連接,但是也可以在收到關(guān)閉幀以后任意時間關(guān)閉連接。例如:如果在合理的時間段內(nèi)沒有收到TCP關(guān)閉指令。
如果客戶端和服務(wù)端咋同一個時間發(fā)送了關(guān)閉幀,兩個終端都會發(fā)送和接收到一條關(guān)閉的消息,并且應(yīng)該認為WebSocket連接已經(jīng)關(guān)閉,同時關(guān)閉底層的TCP連接。
5.5.2 心跳Ping心跳Ping幀包含的操作碼是0x9。
關(guān)閉幀可能包含“應(yīng)用數(shù)據(jù)”。
如果收到了一個心跳Ping幀,那么終端必須發(fā)送一個心跳Pong 幀作為回應(yīng),除非已經(jīng)收到了一個關(guān)閉幀。終端應(yīng)該盡快恢復(fù)Pong幀。Pong幀將會在5.5.3節(jié)討論。
終端可能會在建立連接后與連接關(guān)閉前中間的任意時間發(fā)送Ping幀。
注意:Ping幀可能是用于保活或者用來驗證遠端是否仍然有應(yīng)答。
5.5.3 心跳Pong心跳Ping幀包含的操作碼是0xA。
5.5.2節(jié)詳細說明了Ping幀和Pong幀的要求。
作為回應(yīng)發(fā)送的Pong幀必須完整攜帶Ping幀中傳遞過來的“應(yīng)用數(shù)據(jù)”字段。
如果終端收到一個Ping幀但是沒有發(fā)送Pong幀來回應(yīng)之前的pong幀,那么終端可能選擇用Pong幀來回復(fù)最近處理的那個Ping幀。
Pong幀可以被主動發(fā)送。這會作為一個單項的心跳。預(yù)期外的Pong包的響應(yīng)沒有規(guī)定。
數(shù)據(jù)幀數(shù)據(jù)幀(例如非控制幀)的定義是操作碼的最高位值為0。當(dāng)前定義的數(shù)據(jù)幀操作嗎包含0x1(文本)、0x2(二進制)。操作碼0x3-0x7是被保留作為非控制幀的操作碼。
數(shù)據(jù)幀會攜帶應(yīng)用層/擴展層數(shù)據(jù)。操作碼決定了攜帶的數(shù)據(jù)解析方式:
文本
“負載字段”是用UTF-8編碼的文本數(shù)據(jù)。注意特殊的文本幀可能包含部分UTF-8序列;然而,整個消息必須是有效的UTF-8編碼數(shù)據(jù)。重新組合消息后無效的UTF-8編碼數(shù)據(jù)處理見8.1節(jié)。
二進制
“負載字段”是任意的二進制數(shù)據(jù),二進制數(shù)據(jù)的解析僅僅依靠應(yīng)用層。
5.7 示例一個單幀未添加掩碼的文本消息
0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f (內(nèi)容為"Hello")
一個單幀添加掩碼的文本消息
0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58 (內(nèi)容為Hello")
一個分片的未添加掩碼的文本消息
0x01 0x03 0x48 0x65 0x6c (內(nèi)容為"Hel")
0x80 0x02 0x6c 0x6f (內(nèi)容為”lo")
未添加掩碼的Ping請求和添加掩碼的Ping響應(yīng)(譯者注:即Pong)
0x89 0x05 0x48 0x65 0x6c 0x6c 0x6f (包含內(nèi)容為”Hello", 但是文本內(nèi)容是任意的)
0x8a 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58 (包含內(nèi)容為”Hello", 匹配ping的內(nèi)容)
256字節(jié)的二進制數(shù)據(jù)放入一個未添加掩碼數(shù)據(jù)幀
0x82 0x7E 0x0100 [256 bytes of binary data]
64KB二進制數(shù)據(jù)在一個非掩碼幀中
0x82 0x7F 0x0000000000010000 [65536 bytes of binary data]
這個協(xié)議的設(shè)計初衷是允許擴展的,可以在基礎(chǔ)協(xié)議上增加能力。終端的連接必須在握手的過程中協(xié)商使用的所有擴展。在規(guī)范中提供了從0x3-0x7和0xB-0xF的操作碼,在數(shù)據(jù)幀Header中的“擴展數(shù)據(jù)”字段、frame-rsv1、frame-rsv2、frame-rsv3字段都可以用于擴展。擴展的協(xié)商討論將在以后的9.1節(jié)中詳細討論。下面是一些符合預(yù)期的擴展用法。下面的列表不完整,也不是規(guī)范中內(nèi)容。
“擴展數(shù)據(jù)”可以放置在“負載數(shù)據(jù)“中的應(yīng)用數(shù)據(jù)”之前的位置。
保留的字段可以在每一幀需要時被使用。
保留的操作碼的值可以被定義。
如果需要更多的操作碼,那么保留的操作碼字段可以被定義。
保留的字段或者“擴展”操作碼可以在“負載數(shù)據(jù)”之中的分配額外的位置來定義,這樣可以定義更大的操作碼或者更多的每一幀的字段。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/100798.html
摘要:數(shù)據(jù)幀協(xié)議正文概覽在協(xié)議中,數(shù)據(jù)是通過一系列數(shù)據(jù)幀來進行傳輸?shù)?。注意無論協(xié)議是否使用了,幀都需要添加掩碼。服務(wù)端收到?jīng)]有添加掩碼的數(shù)據(jù)幀以后,必須立即關(guān)閉連接。服務(wù)端禁止在發(fā)送數(shù)據(jù)幀給客戶端時添加掩碼。 概述 本文為WebSocket協(xié)議的第五章,本文翻譯的主要內(nèi)容為WebSocket傳輸?shù)臄?shù)據(jù)相關(guān)內(nèi)容。 數(shù)據(jù)幀(協(xié)議正文) 5.1 概覽 在WebSocket協(xié)議中,數(shù)據(jù)是通過一系列數(shù)...
摘要:概述經(jīng)過半年的搗鼓,終于將協(xié)議全篇翻譯完成。現(xiàn)在將所有章節(jié)全部整理到一篇文章中,方便大家閱讀。如果大家想看具體的翻譯文檔,可以去我的中查看。大家有相關(guān)類型的需要,建議大家可以嘗試下。 概述 經(jīng)過半年的搗鼓,終于將 WebSocket 協(xié)議(RFC6455)全篇翻譯完成?,F(xiàn)在將所有章節(jié)全部整理到一篇文章中,方便大家閱讀。如果大家想看具體的翻譯文檔,可以去我的GitHub中查看。 具體章節(jié)...
摘要:預(yù)備工作序最近正在研究相關(guān)的知識,想著如何能自己實現(xiàn)協(xié)議。監(jiān)聽事件就是協(xié)議的抽象,直接在上面監(jiān)聽已有的事件和事件這兩個事件。表示當(dāng)前數(shù)據(jù)幀為消息的最后一個數(shù)據(jù)幀,此時接收方已經(jīng)收到完整的消息,可以對消息進行處理。 A、預(yù)備工作 1、序 最近正在研究 Websocket 相關(guān)的知識,想著如何能自己實現(xiàn) Websocket 協(xié)議。到網(wǎng)上搜羅了一番資料后用 Node.js 實現(xiàn)該協(xié)議,倒也沒...
摘要:用實現(xiàn)簡單協(xié)議從瀏覽器說起瀏覽器提供的非常簡潔。創(chuàng)建連接連接建立時的回調(diào)收到消息時的回調(diào)連接出錯時的回調(diào)連接終止時的回調(diào)發(fā)送消息告訴我們也就是說,在創(chuàng)建對象時,瀏覽器嘗試與服務(wù)端建立連接發(fā)送請求建立個服務(wù)端一旦收到數(shù)據(jù),就會觸發(fā)。 用 Node 實現(xiàn)簡單 WebSocket 協(xié)議 從瀏覽器 WebSocket API 說起 瀏覽器提供的 WebSocket API 非常簡潔。 let...
摘要:幀協(xié)議讓我們深入了解下幀協(xié)議。目前可用的值該幀接續(xù)前面一幀的有效載荷。該幀包含二進制數(shù)據(jù)。幀有以下幾類長度表示有效載荷的長度。數(shù)據(jù)分片有效載荷數(shù)據(jù)可以被分成多個獨立的幀。接收端會緩沖這些幀直到位有值。 原文請查閱這里,略有改動,本文采用知識共享署名 3.0 中國大陸許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請查閱這里。 這是 JavaScript 工作原...
閱讀 3564·2023-04-26 00:05
閱讀 954·2021-11-11 16:55
閱讀 3522·2021-09-26 09:46
閱讀 3517·2019-08-30 15:56
閱讀 909·2019-08-30 15:55
閱讀 2934·2019-08-30 15:53
閱讀 1940·2019-08-29 17:11
閱讀 814·2019-08-29 16:52