在WebSocket協(xié)議中,數(shù)據(jù)使用幀序列來(lái)傳輸。為避免混淆網(wǎng)絡(luò)中間件(例如攔截代理)和出于安全原因,第10.3節(jié)進(jìn)一步討論,客戶(hù)端必須掩碼(mask)它發(fā)送到服務(wù)器的所有幀(更多詳細(xì)信息請(qǐng)參見(jiàn)5.3節(jié))。(注意不管WebSocket協(xié)議是否運(yùn)行在TLS至上,掩碼都要做。) 當(dāng)收到一個(gè)沒(méi)有掩碼的幀時(shí),服務(wù)器必須關(guān)閉連接。在這種情況下,服務(wù)器可能發(fā)送一個(gè)定義在7.4.1節(jié)的狀態(tài)碼1002(協(xié)議錯(cuò)誤)的Close幀。服務(wù)器必須不掩碼發(fā)送到客戶(hù)端的所有幀。如果客戶(hù)端檢測(cè)到掩碼的幀,它必須關(guān)閉連接。在這種情況下,它可能使用定義在7.4.1節(jié)的狀態(tài)碼1002(協(xié)議錯(cuò)誤)。(這些規(guī)則可能在未來(lái)規(guī)范中放寬。)
基本幀協(xié)議定義了帶有操作碼(opcode)的幀類(lèi)型、負(fù)載長(zhǎng)度、和用于“擴(kuò)展數(shù)據(jù)”與“應(yīng)用數(shù)據(jù)”及它們一起定義的“負(fù)載數(shù)據(jù)”的指定位置。某些字節(jié)和操作嗎保留用于未來(lái)協(xié)議的擴(kuò)展。
一個(gè)數(shù)據(jù)幀可以被客戶(hù)端或者服務(wù)器在打開(kāi)階段握手完成之后和端點(diǎn)發(fā)送Close幀之前的任何時(shí)候傳輸(5.5.1節(jié))。
用于數(shù)據(jù)傳輸部分的報(bào)文格式是通過(guò)本節(jié)中詳細(xì)描述的ABNF來(lái)描述。(注意,不像本文檔的其他章節(jié),本節(jié)中的ABNF是在位(bit)組上操作。每一個(gè)位組的長(zhǎng)度在注釋中指出。在編碼報(bào)文時(shí),最重要的位是在ABNF的最左邊。)下圖給出了幀的高層次概述。在下圖和在本節(jié)后邊指定的ABNF之間沖突的,這個(gè)圖表是權(quá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
指示這個(gè)是消息的最后片段。第一個(gè)片段可能也是最后的片段。
RSV1, RSV2, RSV3: 每個(gè)1 bit
必須是0,除非一個(gè)擴(kuò)展協(xié)商為非零值定義含義。如果收到一個(gè)非零值且沒(méi)有協(xié)商的擴(kuò)展定義這個(gè)非零值的含義,接收端點(diǎn)必須失敗WebSokcket連接。
Opcode: 4 bits
定義了“負(fù)載數(shù)據(jù)”的解釋。如果收到一個(gè)未知的操作碼,接收端點(diǎn)必須失敗WebSocket連接。定義了以下值。
Mask: 1 bit
定義是否“負(fù)載數(shù)據(jù)”是掩碼的。如果設(shè)置為1,一個(gè)掩碼鍵出現(xiàn)在masking-key,且這個(gè)是用于根據(jù)5.3節(jié)解掩碼(unmask)“負(fù)載數(shù)據(jù)”。從客戶(hù)端發(fā)送到服務(wù)器的所有幀有這個(gè)位設(shè)置為1。
Payload length: 7 bits, 7+16 bits, 或者 7+64 bits
“負(fù)載數(shù)據(jù)”的長(zhǎng)度,以字節(jié)為單位:如果0-125,這是負(fù)載長(zhǎng)度。如果126,之后的兩字節(jié)解釋為一個(gè)16位的無(wú)符號(hào)整數(shù)是負(fù)載長(zhǎng)度。如果127,之后的8字節(jié)解釋為一個(gè)64位的無(wú)符號(hào)整數(shù)(最高有效位必須是0)是負(fù)載長(zhǎng)度。多字節(jié)長(zhǎng)度數(shù)量以網(wǎng)絡(luò)字節(jié)順序來(lái)表示。注意,在所有情況下,最小數(shù)量的字節(jié)必須用于編碼長(zhǎng)度,例如,一個(gè)124字節(jié)長(zhǎng)的字符串的長(zhǎng)度不能被編碼為序列126,0,124。負(fù)載長(zhǎng)度是“擴(kuò)展數(shù)據(jù)”長(zhǎng)度+“應(yīng)用數(shù)據(jù)”長(zhǎng)度?!皵U(kuò)展數(shù)據(jù)”長(zhǎng)度可能是零,在這種情況下,負(fù)載長(zhǎng)度是“應(yīng)用數(shù)據(jù)”長(zhǎng)度。
Masking-key: 0 or 4 bytes
客戶(hù)端發(fā)送到服務(wù)器的所有幀通過(guò)一個(gè)包含在幀中的32位值來(lái)掩碼。如果mask位設(shè)置為1,則該字段存在,如果mask位設(shè)置為0,則該字段缺失。詳細(xì)信息請(qǐng)參見(jiàn)5.3節(jié) 客戶(hù)端到服務(wù)器掩碼。
Payload data: (x+y) bytes
“負(fù)載數(shù)據(jù)”定義為“擴(kuò)展數(shù)據(jù)”連接“應(yīng)用數(shù)據(jù)”。
Extension data: x bytes
“擴(kuò)展數(shù)據(jù)”是0字節(jié)除非已經(jīng)協(xié)商了一個(gè)擴(kuò)展。任何擴(kuò)展必須指定“擴(kuò)展數(shù)據(jù)”的長(zhǎng)度,或長(zhǎng)度是如何計(jì)算的,以及擴(kuò)展如何使用必須在打開(kāi)階段握手期間協(xié)商。 如果存在,“擴(kuò)展數(shù)據(jù)”包含在總負(fù)載長(zhǎng)度中。
Application data: y bytes
任意的“應(yīng)用數(shù)據(jù)”,占用“擴(kuò)展數(shù)據(jù)”之后幀的剩余部分?!皯?yīng)用數(shù)據(jù)”的長(zhǎng)度等于負(fù)載長(zhǎng)度減去“擴(kuò)展數(shù)據(jù)”長(zhǎng)度。
基本幀協(xié)議是由以下ABNF[RFC5234]正式定義。重要的是要注意這個(gè)數(shù)據(jù)是二進(jìn)制表示的,而不是ASCII字符。因此,一個(gè)1位長(zhǎng)度的字段取值為%x0 / %x1 是表示為單個(gè)位,其值為0或1,不是以ASCII編碼代表字符“0”或“1”的完整的字節(jié)(8位位組)。4位長(zhǎng)度的字段值介于%0-F之間,是通過(guò)4位表示的,不是通過(guò)ASCII字符或這些值的完整字節(jié)(8位位組)。[RFC5234]沒(méi)有指定字符編碼:“規(guī)則解析為最終值的字符串,有時(shí)候被稱(chēng)為字符。在ABNF中,一個(gè)字符僅僅是一個(gè)非負(fù)整數(shù)。在某些上下文中,一個(gè)值到一個(gè)字符集的特定映射(編碼)將被指定?!?在這里,指定的編碼是二進(jìn)制編碼,每一個(gè)最終值是編碼到指定數(shù)量的比特中,每個(gè)字段是不同的。
ws-frame = frame-fin ; 1位長(zhǎng)度
frame-rsv1 ; 1位長(zhǎng)度
frame-rsv2 ; 1位長(zhǎng)度
frame-rsv3 ; 1位長(zhǎng)度
frame-opcode ; 4位長(zhǎng)度
frame-masked ; 1位長(zhǎng)度
frame-payload-length ; 或者 7、 7+16、
; 或者7+64 位長(zhǎng)度
[ frame-masking-key ] ; 32位長(zhǎng)度
frame-payload-data ; n*8位長(zhǎng)度; n>=0
frame-fin = %x0 ; 這條消息后續(xù)還有更多的幀
/ %x1 ; 這條消息的最終幀
; 1位長(zhǎng)度
frame-rsv1 = %x0 / %x1
; 1位長(zhǎng)度,必須是0,除非協(xié)商其他
frame-rsv2 = %x0 / %x1
; 1位長(zhǎng)度,必須是0,除非協(xié)商其他
frame-rsv3 = %x0 / %x1
; 1位長(zhǎng)度,必須是0,除非協(xié)商其他
frame-opcode = frame-opcode-non-control /
frame-opcode-control /
frame-opcode-cont
frame-opcode-cont = %x0 ; 幀繼續(xù)
frame-opcode-non-control= %x1 ; 文本幀
/ %x2 ; 二進(jìn)制幀
/ %x3-7
; 4位長(zhǎng)度,保留用于未來(lái)的非控制幀
frame-opcode-control = %x8 ; 連接關(guān)閉
/ %x9 ; ping
/ %xA ; pong
/ %xB-F ; 保留用于未來(lái)的控制幀
; 4位長(zhǎng)度
frame-masked = %x0
; 幀沒(méi)有掩碼,沒(méi)有frame-masking-key
/ %x1
; 幀被掩碼,存在frame-masking-key
; 1位長(zhǎng)度
frame-payload-length = ( %x00-7D )
/ ( %x7E frame-payload-length-16 )
/ ( %x7F frame-payload-length-63 )
; 分別7, 7+16, or 7+64位長(zhǎng)度
frame-payload-length-16 = %x0000-FFFF ; 16位長(zhǎng)度
frame-payload-length-63 = %x0000000000000000-7FFFFFFFFFFFFFFF
; 64位長(zhǎng)度
frame-masking-key = 4( %x00-FF )
; 僅當(dāng)frame-masked 是 1時(shí)存在
; 32位長(zhǎng)度
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 )
; 保留用于未來(lái)擴(kuò)展
; n*8 位長(zhǎng)度,n >= 0
frame-masked-application-data = *( %x00-FF )
; n*8 位長(zhǎng)度,n >= 0
frame-unmasked-extension-data = *( %x00-FF )
; 保留用于未來(lái)擴(kuò)展
; n*8 位長(zhǎng)度,n >= 0
frame-unmasked-application-data = *( %x00-FF )
; n*8 位長(zhǎng)度,n >= 0
一個(gè)掩碼的幀必須有5.2節(jié)定義的字段frame-masked設(shè)置為1。 掩碼鍵完全包含在幀中,5.2節(jié)定義的frame-masking-key。它用于掩碼定義在相同章節(jié)的frame-payload-data 中的“負(fù)載數(shù)據(jù)”,其包含“擴(kuò)展數(shù)據(jù)”和“應(yīng)用數(shù)據(jù)”。
掩碼鍵是由客戶(hù)端隨機(jī)選擇的32位值。當(dāng)準(zhǔn)備一個(gè)掩碼的幀時(shí),客戶(hù)端必須從允許的32位值集合中選擇一個(gè)新的掩碼鍵。掩碼鍵需要是不可預(yù)測(cè)的;因此,掩碼鍵必須來(lái)自一個(gè)強(qiáng)大的熵源,且用于給定幀的掩碼鍵必須不容易被服務(wù)器/代理預(yù)測(cè)用于后續(xù)幀的掩碼鍵。掩碼鍵的不可預(yù)測(cè)性對(duì)防止惡意應(yīng)用的作者選擇出現(xiàn)在報(bào)文上的字節(jié)是必要的。RFC 4086[RFC4086]討論了什么需要一個(gè)用于安全敏感應(yīng)用的合適的熵源。
掩碼不影響“負(fù)載數(shù)據(jù)”的長(zhǎng)度。變換掩碼數(shù)據(jù)到解掩碼數(shù)據(jù),或反之亦然,以下算法被應(yīng)用。相同的算法應(yīng)用,不管轉(zhuǎn)化的方向,例如,相同的步驟即應(yīng)用到掩碼數(shù)據(jù)也應(yīng)用到解掩碼數(shù)據(jù)。
變換數(shù)據(jù)的八位位組i ("transformed-octet-i")是原始數(shù)據(jù)的八位位組i("original-octet-i")異或(XOR)i取模4位置的掩碼鍵的八位位組("masking-key-octet-j"):
j = i MOD 4
transformed-octet-i = original-octet-i XOR masking-key-octet-j
負(fù)載長(zhǎng)度,在幀中以frame-payload-length表示,不包括掩碼鍵的長(zhǎng)度。它是“負(fù)載數(shù)據(jù)”的長(zhǎng)度,例如,跟在掩碼鍵后邊的字節(jié)數(shù)。
分片的主要目的是允許當(dāng)消息開(kāi)始但不必緩沖該消息時(shí)發(fā)送一個(gè)未知大小的消息。如果消息不能被分片,那么端點(diǎn)將不得不緩沖整個(gè)消息以便在首字節(jié)發(fā)生之前統(tǒng)計(jì)出它的長(zhǎng)度。對(duì)于分片,服務(wù)器或中間件可以選擇一個(gè)合適大小的緩沖,當(dāng)緩沖滿(mǎn)時(shí),寫(xiě)一個(gè)片段到網(wǎng)絡(luò)。 第二個(gè)分片的用例是用于多路復(fù)用,一個(gè)邏輯通道上的一個(gè)大消息獨(dú)占輸出通道是不可取的,因此多路復(fù)用需要可以分割消息為更小的分段來(lái)更好的共享輸出通道。(注意,多路復(fù)用擴(kuò)展在本文檔中沒(méi)有描述)
除非另有擴(kuò)展指定,幀沒(méi)有語(yǔ)義含義。一個(gè)中間件可能合并且/或分割幀,如果客戶(hù)端和服務(wù)器沒(méi)有協(xié)商擴(kuò)展;或如果已協(xié)商了一些擴(kuò)展,但中間件理解所有協(xié)商的擴(kuò)展且知道如何去合并且/或分割在這些擴(kuò)展中存在的幀。這方面的一個(gè)含義是,在沒(méi)有擴(kuò)展情況下,發(fā)送者和接收者必須不依賴(lài)于特定幀邊界的存在。
以下規(guī)則應(yīng)用到分片:
一個(gè)分片的消息由單個(gè)帶有FIN位清零(5.2節(jié))和一個(gè)非0操作碼的幀組成,跟隨零個(gè)或多個(gè)帶有FIN位清零和操作碼設(shè)置為0的幀,且終止于一個(gè)帶有FIN位設(shè)置且0操作碼的幀。一個(gè)分片的消息概念上是等價(jià)于單個(gè)大的消息,其負(fù)載是等價(jià)于按順序串聯(lián)片段的負(fù)載;然而,在存在擴(kuò)展的情況下,這個(gè)可能不適用擴(kuò)展定義的“擴(kuò)展數(shù)據(jù)”存在的解釋。例如,“擴(kuò)展數(shù)據(jù)”可能僅在首個(gè)片段開(kāi)始處存在且應(yīng)用到隨后的片段,或 “擴(kuò)展數(shù)據(jù)”可以存在于僅用于到特定片段的每個(gè)片段。在沒(méi)有“擴(kuò)展數(shù)據(jù)”的情況下,以下例子展示了分片如何工作。 例子:對(duì)于一個(gè)作為三個(gè)片段發(fā)送的文本消息,第一個(gè)片段將有一個(gè)0x1操作碼和一個(gè)FIN位清零,第二個(gè)片段將有一個(gè)0x0操作碼和一個(gè)FIN位清零,且第三個(gè)片段將有0x0操作碼和一個(gè)FIN位設(shè)置。
控制幀(參見(jiàn)5.5節(jié))可能被注入到一個(gè)分片消息的中間。控制幀本身必須不被分割。
注意:如果控制幀不能被插入,一個(gè)ping延遲,例如,如果跟著一個(gè)大消息將是非常長(zhǎng)的。因此,要求在分片消息的中間處理控制幀。
實(shí)現(xiàn)注意:在沒(méi)有任何擴(kuò)展時(shí),一個(gè)接收者不必按順序緩沖整個(gè)幀來(lái)處理它。例如,如果使用了一個(gè)流式API,一個(gè)幀的一部分能被交付到應(yīng)用。但是,請(qǐng)注意這個(gè)假設(shè)可能不適用所有未來(lái)的WebSocket擴(kuò)展。
控制幀由操作碼確定,其中操作碼最重要的位是1。當(dāng)前定義的用于控制幀的操作碼包括0x8 (Close)、0x9(Ping)、和0xA(Pong)。 操作碼0xB-0xF保留用于未來(lái)尚未定義的控制幀。
控制幀用于傳達(dá)有關(guān)WebSocket的狀態(tài)??刂茙梢圆迦氲椒制⒌闹虚g。
所有控制幀必須有一個(gè)125字節(jié)的負(fù)載長(zhǎng)度或更少, 必須不被分段。
關(guān)閉(Close)幀包含0x8操作碼。
關(guān)閉幀可以包含內(nèi)容體(“幀的“應(yīng)用數(shù)據(jù)”部分)指示一個(gè)關(guān)閉的原因,例如端點(diǎn)關(guān)閉了、端點(diǎn)收到的幀太大、或端點(diǎn)收到的幀不符合端點(diǎn)期望的格式。如果有內(nèi)容體,內(nèi)容體的頭兩個(gè)字節(jié)必須是2字節(jié)的無(wú)符號(hào)整數(shù)(按網(wǎng)絡(luò)字節(jié)順序)代表一個(gè)在7.4節(jié)的/code/值定義的狀態(tài)碼。跟著2字節(jié)的整數(shù),內(nèi)容體可以包含UTF-8編碼的/reason/值,本規(guī)范沒(méi)有定義它的解釋。數(shù)據(jù)不必是人類(lèi)可讀的但可能對(duì)調(diào)試或傳遞打開(kāi)連接的腳本相關(guān)的信息是有用的。由于數(shù)據(jù)不保證人類(lèi)可讀,客戶(hù)端必須不把它顯示給最終用戶(hù)。
客戶(hù)端發(fā)送到服務(wù)器的關(guān)閉幀必須根據(jù)5.3節(jié)被掩碼。
在應(yīng)用發(fā)送關(guān)閉幀之后,必須不發(fā)送任何更多的數(shù)據(jù)幀。
如果一個(gè)端點(diǎn)接收到一個(gè)關(guān)閉幀且先前沒(méi)有發(fā)送一個(gè)關(guān)閉幀,端點(diǎn)必須在響應(yīng)中發(fā)送一個(gè)關(guān)閉幀。(當(dāng)在響應(yīng)中發(fā)生關(guān)閉幀時(shí),端點(diǎn)通常回送它接收到的狀態(tài)碼) 它應(yīng)該根據(jù)實(shí)際情況盡快這樣做。端點(diǎn)可以延遲發(fā)送關(guān)閉幀知道它當(dāng)前消息發(fā)送了(例如,如果一個(gè)分片消息的大多數(shù)已經(jīng)發(fā)送了,端點(diǎn)可以發(fā)送剩余的片段在發(fā)送一個(gè)關(guān)閉幀之前)。但是,不保證一個(gè)已經(jīng)發(fā)送關(guān)閉幀的端點(diǎn)將繼續(xù)處理數(shù)據(jù)。 發(fā)送并接收一個(gè)關(guān)閉消息后,一個(gè)端點(diǎn)認(rèn)為WebSocket連接關(guān)閉了且必須關(guān)閉底層的TCP連接。服務(wù)器必須立即關(guān)閉底層TCP連接,客戶(hù)端應(yīng)該等待服務(wù)器關(guān)閉連接但可能在發(fā)送和接收一個(gè)關(guān)閉消息之后的任何時(shí)候關(guān)閉連接,例如,如果它沒(méi)有在一個(gè)合理的時(shí)間周期內(nèi)接收到服務(wù)器的TCP關(guān)閉。
如果客戶(hù)端和服務(wù)器同時(shí)都發(fā)送了一個(gè)關(guān)閉消息,兩個(gè)端點(diǎn)都將發(fā)送和接收一個(gè)關(guān)閉消息且應(yīng)該認(rèn)為WebSocket連接關(guān)閉了并關(guān)閉底層TCP連接。
Ping幀包含0x9操作碼。
Ping幀可以包含“應(yīng)用數(shù)據(jù)”。
當(dāng)收到一個(gè)Ping幀時(shí),一個(gè)端點(diǎn)必須在響應(yīng)中發(fā)送一個(gè)Pong幀,除非它早已接收到一個(gè)關(guān)閉幀。它應(yīng)該盡可能快地以Pong幀響應(yīng)。Pong幀在5.5.3節(jié)討論。
一個(gè)端點(diǎn)可以在連接建立之后并在連接關(guān)閉之前的任何時(shí)候發(fā)送一個(gè)Ping幀。 注意:一個(gè)Ping即可以充當(dāng)一個(gè)keepalive,也可以作為驗(yàn)證遠(yuǎn)程端點(diǎn)仍可響應(yīng)的手段。
Pong幀包含一個(gè)0xA操作碼。
5.5.2節(jié)詳細(xì)說(shuō)明了應(yīng)用Ping和Pong幀的要求。
一個(gè)Pong幀在響應(yīng)中發(fā)送到一個(gè)Ping幀必須有在將回復(fù)的Ping幀的消息內(nèi)容體中發(fā)現(xiàn)的相同的“應(yīng)用數(shù)據(jù)”。
如果端點(diǎn)接收到一個(gè)Ping幀且尚未在響應(yīng)中發(fā)送Pong幀到之前的Ping幀,端點(diǎn)可以選擇僅為最近處理的Ping幀發(fā)送一個(gè)Pong幀。
一個(gè)Pong幀可以未經(jīng)請(qǐng)求的發(fā)送。這個(gè)充當(dāng)單向的心跳(heartbeat)。到未經(jīng)請(qǐng)求的Pong幀的一個(gè)響應(yīng)是不期望的。
數(shù)據(jù)幀(例如,非控制幀)由操作碼最高位是0的操作碼標(biāo)識(shí)。當(dāng)前為數(shù)據(jù)幀定義的操作碼包括0x1(文本)、0x2(二進(jìn)制)。操作碼0x3-0x7保留用于未來(lái)尚未定義的非控制幀。
數(shù)據(jù)幀攜帶應(yīng)用層和/或擴(kuò)展層數(shù)據(jù)。操作碼決定了數(shù)據(jù)的解釋?zhuān)?/p>
Text
“負(fù)載數(shù)據(jù)”是編碼為UTF-8的文本數(shù)據(jù)。注意,一個(gè)特定的文本幀可能包括部分UTF-8序列;不管怎么樣,整個(gè)消息必須包含有效的UTF-8。重新組裝的消息中的無(wú)效的UTF-8的處理描述在8.1節(jié)。
Binary
“負(fù)載數(shù)據(jù)”是隨意的二進(jìn)制數(shù)據(jù),其解釋僅僅是在應(yīng)用層。
未掩碼文件消息的單個(gè)幀
0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f (包含 "Hello")
掩碼的文本消息的單個(gè)幀
0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58 (包含 "Hello")
一個(gè)分片的未掩碼的文本消息
0x01 0x03 0x48 0x65 0x6c (包含 "Hel")
0x80 0x02 0x6c 0x6f (包含 "lo")
未掩碼的Ping請(qǐng)求和掩碼的Ping響應(yīng)
0x89 0x05 0x48 0x65 0x6c 0x6c 0x6f
(包含內(nèi)容體"Hello"、但內(nèi)容體的內(nèi)容是隨意的)
0x8a 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58
(包含內(nèi)容體"Hello"、匹配ping的內(nèi)容體)
單個(gè)未掩碼幀中的256字節(jié)的二進(jìn)制消息
0x82 0x7E 0x0100 [256字節(jié)的二進(jìn)制數(shù)據(jù)]
單個(gè)未掩碼幀中的64KB的二進(jìn)制消息
0x82 0x7F 0x0000000000010000 [65536字節(jié)的二進(jìn)制數(shù)據(jù)]
協(xié)議被設(shè)計(jì)為允許擴(kuò)展,這將增加功能到基礎(chǔ)協(xié)議。端點(diǎn)的一個(gè)連接必須在打開(kāi)階段握手期間協(xié)商使用的任何擴(kuò)展。本規(guī)范提供了用于擴(kuò)展的操作碼0x3到0x7和0xB到0xF、“擴(kuò)展數(shù)據(jù)”字段、和幀-rsv1、幀rsv2、和幀rsv3幀頭位。9.1節(jié)進(jìn)一步討論了擴(kuò)展協(xié)商。以下是一些預(yù)期使用的擴(kuò)展。這個(gè)列表是不完整的也不規(guī)范的。
更多建議: