RFC6455-The WebSocket protocol 之六:5. Data Framing

5.  Data Framing

數據塊

5.1.  Overview
   In the WebSocket Protocol, data is transmitted using a sequence of
   frames.  To avoid confusing network intermediaries (such as
   intercepting proxies) and for security reasons that are further
   discussed in Section 10.3, a client MUST mask all frames that it
   sends to the server (see Section 5.3 for further details).  (Note
   that masking is done whether or not the WebSocket Protocol is running
   over TLS.)  The server MUST close the connection upon receiving a
   frame that is not masked.  In this case, a server MAY send a Close
   frame with a status code of 1002 (protocol error) as defined in
   Section 7.4.1.  A server MUST NOT mask any frames that it sends to
   the client.  A client MUST close a connection if it detects a masked
   frame.  In this case, it MAY use the status code 1002 (protocol
   error) as defined in Section 7.4.1.  (These rules might be relaxed in
   a future specification.)
   The base framing protocol defines a frame type with an opcode, a
   payload length, and designated locations for "Extension data" and
   "Application data", which together define the "Payload data".
   Certain bits and opcodes are reserved for future expansion of the
   protocol.

概述

在WebSocket協議中,數據通過數據塊的序列進行傳輸。爲了防止混淆網絡中介(例如攔截代理)以及在10.3中提到的安全原因,客戶端必須把發往服務端的所有數據進行掩碼(mask)。(注意無論是否在TLS上運行,掩碼過程都會執行)。服務端一旦接收到非掩碼的數據它必須關閉連接。這種情況下,服務端會發送一個帶有1002狀態碼的關閉數據塊,就像7.1中定義的一樣。服務端發往客戶端的數據庫都不能掩碼。客戶端一旦接收到掩碼的數據它必須關閉連接。這種情況下,客戶端可能會使用到7.4.1節中定義的1002狀態碼。(該規則在將來可能會放鬆)。

基本的數據塊協議定義了一種數據庫類型:一個操作碼,一個負載長度,擴展數據和應用數據的存放位置,這些一起構成了負載數據("Payload data")。爲了方便將來的擴展,預留了一些位和操作碼。

 

   A data frame MAY be transmitted by either the client or the server at
   any time after opening handshake completion and before that endpoint
   has sent a Close frame (Section 5.5.1).

在握手打開後終端發送關閉數據塊之前,一個數據塊可能在任何時候被客戶端或服務端傳輸。

 

5.2.  Base Framing Protocol
   This wire format for the data transfer part is described by the ABNF
   [RFC5234] given in detail in this section.  (Note that, unlike in
   other sections of this document, the ABNF in this section is
   operating on groups of bits.  The length of each group of bits is
   indicated in a comment.  When encoded on the wire, the most
   significant bit is the leftmost in the ABNF).  A high-level overview
   of the framing is given in the following figure.  In a case of
   conflict between the figure below and the ABNF specified later in
   this section, the figure is authoritative.

5.2 基本數據塊協議

在本節中會對ABNF中描述的數據傳輸的傳輸格式進行詳細說明。(注意,與其它章節不同,本節中提到的ABNF是一組二進制數字。每一組二進制編碼的長度都在數據塊內容中表示。當進行編碼時,ABNF最左邊的位是最重要的)。在隨後的圖形中對數據塊給出了更高級別的概述。當下圖所示與ABNF所定義的有衝突的話,下圖所示的更爲權威。

 

FIN:  1 bit
     Indicates that this is the final fragment in a message.  The first
     fragment MAY also be the final fragment.
FIN:1位
代表這是消息中的最後一個數據塊。第一個數據塊可能也是最後一個數據塊。

   RSV1, RSV2, RSV3:  1 bit each
      MUST be 0 unless an extension is negotiated that defines meanings
      for non-zero values.  If a nonzero value is received and none of
      the negotiated extensions defines the meaning of such a nonzero
      value, the receiving endpoint MUST _Fail the WebSocket
      Connection_.
RSV1, RSV2, RSV3:1位
除非在將來的擴展中爲非0值定義了明確的含義否則必須爲0.假如擴展沒有定義非0值的含義,當接收到一個非0的值時,接收方必須捨棄這個WebSocket連接。

   Opcode:  4 bits
      Defines the interpretation of the "Payload data".  If an unknown
      opcode is received, the receiving endpoint MUST _Fail the
      WebSocket Connection_.  The following values are defined.
      *  %x0 denotes a continuation frame
      *  %x1 denotes a text frame
      *  %x2 denotes a binary frame
      *  %x3-7 are reserved for further non-control frames
      *  %x8 denotes a connection close
      *  %x9 denotes a ping
      *  %xA denotes a pong
      *  %xB-F are reserved for further control frames
操作碼:4位
定義了負載數據的解釋。當接收到一個不能識別的操作碼時,接收方必須捨棄這個WebSocket連接。以下是定義好的操作碼:
 *  %x0 表示一個持續的數據塊
      *  %x1 表示一個文本數據塊
      *  %x2 表示一個二進制數據塊
      *  %x3-7 爲將來控制外數據塊預留
      *  %x8 表示連接關閉
      *  %x9 表示ping(denotes a ping)
      *  %xA 表示乒乓球(denotes a pong)
      *  %xB-F 爲將來控制數據塊預留

   Mask:  1 bit
      Defines whether the "Payload data" is masked.  If set to 1, a
      masking key is present in masking-key, and this is used to unmask
      the "Payload data" as per Section 5.3.  All frames sent from
      client to server have this bit set to 1.
掩碼:1位
定義負載數據是否進行了掩碼。如果設置爲1,需要在masking-key中提供一個掩碼鑰匙,用來對負載數據進行解掩碼。所有從客戶端發往服務端的數據塊該位都是1。

  

Payload length:  7 bits, 7+16 bits, or 7+64 bits
      The length of the "Payload data", in bytes: if 0-125, that is the
      payload length.  If 126, the following 2 bytes interpreted as a
      16-bit unsigned integer are the payload length.  If 127, the
      following 8 bytes interpreted as a 64-bit unsigned integer (the
      most significant bit MUST be 0) are the payload length.  Multibyte
      length quantities are expressed in network byte order.  Note that
      in all cases, the minimal number of bytes MUST be used to encode
      the length, for example, the length of a 124-byte-long string
      can’t be encoded as the sequence 126, 0, 124.  The payload length
      is the length of the "Extension data" + the length of the
      "Application data".  The length of the "Extension data" may be
      zero, in which case the payload length is the length of the
      "Application data".
負載數據長度:7位,7+16位,或7+64位。
負載數據長度,假如是0-125,是負載長度。假如是126,後面的2個字節解析的16位的無符號整數作爲負載長度。假如是127,後面的8個字節解析的64位的無符號整數(標誌位必須是0)作爲負載長度。多字節長度數量按照網絡順序進行表示。注意,在所有情況下,代表最小位數的數字(7位二進制轉換成的數字)應該能代表數據的長度,例如124位長的字符不能被編碼成126(太大)、0(太小)、124(不知道爲什麼)長度的序列。負載數據長度是擴展數據加應用數據長度的和。當擴展數據長度爲0時,負載長度就是業務數據的長度。

   Masking-key:  0 or 4 bytes
      All frames sent from the client to the server are masked by a
      32-bit value that is contained within the frame.  This field is
      present if the mask bit is set to 1 and is absent if the mask bit
      is set to 0.  See Section 5.3 for further information on client-
      to-server masking.
掩碼鑰匙:0或4字節
所有從客戶端發往服務端的數據塊都經過包含在數據塊中的一個32位長的鑰匙進行掩碼。這個值當掩碼標誌設置爲1的時候存在,設置爲0的時候不存在。參照5.3節瞭解關於客戶端到服務端掩碼的更多的知識。


   Payload data:  (x+y) bytes
      The "Payload data" is defined as "Extension data" concatenated
      with "Application data".
負載數據:(x + y)字節
負載數據指的是擴展數據與應用數據的和。

   Extension data:  x bytes
      The "Extension data" is 0 bytes unless an extension has been
      negotiated.  Any extension MUST specify the length of the
      "Extension data", or how that length may be calculated, and how
      the extension use MUST be negotiated during the opening handshake.
      If present, the "Extension data" is included in the total payload
      length.

擴展數據:x 位字節
擴展數據的長度爲0,除非指定了擴展信息。在握手過程中所有的擴展信息必須指定擴展數據的長度,或者長度的計算方式,以及如何使用擴展信息。如果存在,擴展數據被包含在整個負載長度裏面。

    Application data:  y bytes
      Arbitrary "Application data", taking up the remainder of the frame
      after any "Extension data".  The length of the "Application data"
      is equal to the payload length minus the length of the "Extension
      data".

應用數據:y位字節

任意的應用數據,佔據了擴展數據之後的所有位置。應用數據的長度等於負載長度減去擴展數據的長度。


   The base framing protocol is formally defined by the following ABNF
   [RFC5234].  It is important to note that the representation of this
   data is binary, not ASCII characters.  As such, a field with a length
   of 1 bit that takes values %x0 / %x1 is represented as a single bit
   whose value is 0 or 1, not a full byte (octet) that stands for the
   characters "0" or "1" in the ASCII encoding.  A field with a length
   of 4 bits with values between %x0-F again is represented by 4 bits,
   again NOT by an ASCII character or full byte (octet) with these
   values.  [RFC5234] does not specify a character encoding: "Rules
   resolve into a string of terminal values, sometimes called
   characters.  In ABNF, a character is merely a non-negative integer.
   In certain contexts, a specific mapping (encoding) of values into a
   character set (such as ASCII) will be specified."  Here, the
   specified encoding is a binary encoding where each terminal value is
   encoded in the specified number of bits, which varies for each field.

 基本的數據塊協議由隨後的ABNF定義。需要特別注意的是數據的展現形式是二進制,不是ASCII碼。因此,值爲0或1的1位長的字段以單個位數的形式展現,而不是ASCII中的1個完整的代表“0”或“1”的字節。一個長度爲4位取值範圍在0-F的字段以4位的形式展現,不同於ASCII碼或這些值的完整的字節。[RFC5234]沒有指定字符編碼,有時把字符串分解爲最終的形式的值,稱之爲字符(characters)。在ABNF中,一個字符僅僅只是一個無符號整數。在特定的上下文中,轉換成另外一個字符集(例如ASCII)的編碼方式會被指定。在這裏,特殊的編碼方式就是二進制編碼, 每一個最終的值都用特殊位數編碼,每一個字段都不一樣。

    ws-frame                = frame-fin           ; 1 bit in length
                              frame-rsv1          ; 1 bit in length
                              frame-rsv2          ; 1 bit in length
                              frame-rsv3          ; 1 bit in length
                              frame-opcode        ; 4 bits in length
                              frame-masked        ; 1 bit in length
                              frame-payload-length   ; either 7, 7+16,
                                                     ; or 7+64 bits in
                                                     ; length
                              [ frame-masking-key ]  ; 32 bits in length
                              frame-payload-data     ; n*8 bits in
                                                     ; length, where
                                                     ; n >= 0
    frame-fin               = %x0 ; more frames of this message follow
                            / %x1 ; final frame of this message
                                  ; 1 bit in length
    frame-rsv1              = %x0 / %x1
                              ; 1 bit in length, MUST be 0 unless
                              ; negotiated otherwise
    frame-rsv2              = %x0 / %x1
                              ; 1 bit in length, MUST be 0 unless
                              ; negotiated otherwise
    frame-rsv3              = %x0 / %x1
                              ; 1 bit in length, MUST be 0 unless
                              ; negotiated otherwise

    frame-opcode            = frame-opcode-non-control /
                              frame-opcode-control /
                              frame-opcode-cont
    frame-opcode-cont       = %x0 ; frame continuation
    frame-opcode-non-control= %x1 ; text frame
                            / %x2 ; binary frame
                            / %x3-7
                            ; 4 bits in length,
                            ; reserved for further non-control frames
    frame-opcode-control    = %x8 ; connection close
                            / %x9 ; ping
                            / %xA ; pong
                            / %xB-F ; reserved for further control
                                    ; frames
                                    ; 4 bits in length

    frame-masked            = %x0
                            ; frame is not masked, no frame-masking-key
                            / %x1
                            ; frame is masked, frame-masking-key present
                            ; 1 bit in length
    frame-payload-length    = ( %x00-7D )
                            / ( %x7E frame-payload-length-16 )
                            / ( %x7F frame-payload-length-63 )
                            ; 7, 7+16, or 7+64 bits in length,
                            ; respectively
    frame-payload-length-16 = %x0000-FFFF ; 16 bits in length
    frame-payload-length-63 = %x0000000000000000-7FFFFFFFFFFFFFFF
                            ; 64 bits in length
    frame-masking-key       = 4( %x00-FF )
                              ; present only if frame-masked is 1
                              ; 32 bits in length
    frame-payload-data      = (frame-masked-extension-data
                               frame-masked-application-data)
                            ; when frame-masked is 1
                              / (frame-unmasked-extension-data
                                frame-unmasked-application-data)
                            ; when frame-masked is 0
    frame-masked-extension-data     = *( %x00-FF )
                            ; reserved for future extensibility
                            ; n*8 bits in length, where n >= 0
    frame-masked-application-data   = *( %x00-FF )
                            ; n*8 bits in length, where n >= 0
    frame-unmasked-extension-data   = *( %x00-FF )
                            ; reserved for future extensibility
                            ; n*8 bits in length, where n >= 0
    frame-unmasked-application-data = *( %x00-FF )
                            ; n*8 bits in length, where n >= 0

5.3.  Client-to-Server Masking
   A masked frame MUST have the field frame-masked set to 1, as defined
   in Section 5.2.

一個需要掩碼的數據塊必須把字段frame-masked設置爲1,就像在5.2節中定義的那樣。

   The masking key is contained completely within the frame, as defined
   in Section 5.2 as frame-masking-key.  It is used to mask the "Payload
   data" defined in the same section as frame-payload-data, which
   includes "Extension data" and "Application data".

掩碼鑰匙包含在數據塊中,就像5.2節中定義的那樣以frame-masking-key字段表示。它用來對負載數據進行掩碼形成負載數據塊,負載數據包含擴展數據與應用數據兩部分。


   The masking key is a 32-bit value chosen at random by the client.
   When preparing a masked frame, the client MUST pick a fresh masking
   key from the set of allowed 32-bit values.  The masking key needs to
   be unpredictable; thus, the masking key MUST be derived from a strong
   source of entropy, and the masking key for a given frame MUST NOT
   make it simple for a server/proxy to predict the masking key for a
   subsequent frame.  The unpredictability of the masking key is
   essential to prevent authors of malicious applications from selecting
   the bytes that appear on the wire.  RFC 4086 [RFC4086] discusses what
   entails a suitable source of entropy for security-sensitive
   applications.

掩碼鑰匙是客戶端隨機選擇的32位的值。當準備一個掩碼的數據塊,客戶端必須從允許的32位的值中選擇一個新的掩碼鑰匙。掩碼鑰匙需要是不可預知的;因此,得到掩碼鑰匙需要佔用大量的源,而且對於服務端或代理來說隨後的數據塊中的掩碼鑰匙必須很難去預測。掩碼鑰匙的不可預知性對於防止惡意應用的作者截取網絡上的數據至關重要。RFC 4086討論了對於安全敏感的應用的適當的源(a suitable source of entropy)需要什麼。


   The masking does not affect the length of the "Payload data".  To
   convert masked data into unmasked data, or vice versa, the following
   algorithm is applied.  The same algorithm applies regardless of the
   direction of the translation, e.g., the same steps are applied to
   mask the data as to unmask the data.

掩碼不影響負載數據的長度。把掩碼數據解碼,反之亦然,下面的算法都適用。算法是一樣的,與轉換的方向無關,例如掩碼數據與解碼數據的過程是一樣的。


   Octet i of the transformed data ("transformed-octet-i") is the XOR of
   octet i of the original data ("original-octet-i") with octet at index
   i modulo 4 of the masking key ("masking-key-octet-j"):
     j                   = i MOD 4
     transformed-octet-i = original-octet-i XOR masking-key-octet-j
   The payload length, indicated in the framing as frame-payload-length,
   does NOT include the length of the masking key.  It is the length of
   the "Payload data", e.g., the number of bytes following the masking
   key.

轉換後的8字節數據(transformed-octet-i)是源數據(8字節數據original-octet-i)與掩碼鑰匙異或的結果,掩碼鑰匙(j)的值是源數據與4取餘:

j = i MOD 4

transformed-octet-i = original-octet-i XOR masking-key-octet-j

負載長度,即負載數據塊長度,不包含掩碼鑰匙的長度。它是負載數據的長度,緊跟在掩碼鑰匙之後。

 

5.4.  Fragmentation

5.4 分片
   The primary purpose of fragmentation is to allow sending a message
   that is of unknown size when the message is started without having to
   buffer that message.  If messages couldn’t be fragmented, then an
   endpoint would have to buffer the entire message so its length could
   be counted before the first byte is sent.  With fragmentation, a
   server or intermediary may choose a reasonable size buffer and, when
   the buffer is full, write a fragment to the network.
   A secondary use-case for fragmentation is for multiplexing, where it
   is not desirable for a large message on one logical channel to
   monopolize the output channel, so the multiplexing needs to be free   to split the message into smaller fragments to better share the
   output channel.  (Note that the multiplexing extension is not
   described in this document.)

在不必緩存整個消息的情況下開始發送消息的場景下,分片的主要目的是允許發送不知道大小的消息。如果消息不進行分片,必須有一個終端緩存整個消息,這樣在消息發送之前它的長度就已經計算出來了。在分片的情況下,服務端或代理需要選擇一個合適大小的緩存,當緩存滿了之後,才向網絡寫數據。

分片的第二種場景是在多路情況下,一個大數據量的消息獨佔整個輸出通道是不合適的,因此多路情況下把消息分成小的片共享輸出通道是更好的選擇。(注意,多路擴展在本文中不涉及。)


   Unless specified otherwise by an extension, frames have no semantic
   meaning.  An intermediary might coalesce and/or split frames, if no
   extensions were negotiated by the client and the server or if some
   extensions were negotiated, but the intermediary understood all the
   extensions negotiated and knows how to coalesce and/or split frames
   in the presence of these extensions.  One implication of this is that
   in absence of extensions, senders and receivers must not depend on
   the presence of specific frame boundaries.

除非特殊指定否則對於一個擴展來說,在數據塊中沒有任何含義。當客戶端和服務端沒有指定擴展,或者指定了一些擴展而中介識別所有的擴展並知道如何利用這些擴展對數據塊進行組合或分解,該中介可能會組合或分解數據塊。這意味着如果沒有指定擴展,發送方和接收方不能依賴特定數據邊界的存在。


   The following rules apply to fragmentation:

以下是分片的規則:
   o  An unfragmented message consists of a single frame with the FIN
      bit set (Section 5.2) and an opcode other than 0.

不分片的消息由一個獨立的數據塊組成,包含FIN結束符和非0的操作碼。


   o  A fragmented message consists of a single frame with the FIN bit
      clear and an opcode other than 0, followed by zero or more frames
      with the FIN bit clear and the opcode set to 0, and terminated by
      a single frame with the FIN bit set and an opcode of 0.  A
      fragmented message is conceptually equivalent to a single larger
      message whose payload is equal to the concatenation of the
      payloads of the fragments in order; however, in the presence of
      extensions, this may not hold true as the extension defines the
      interpretation of the "Extension data" present.  For instance,
      "Extension data" may only be present at the beginning of the first
      fragment and apply to subsequent fragments, or there may be
      "Extension data" present in each of the fragments that applies
      only to that particular fragment.  In the absence of "Extension
      data", the following example demonstrates how fragmentation works.
      EXAMPLE: For a text message sent as three fragments, the first
      fragment would have an opcode of 0x1 and a FIN bit clear, the
      second fragment would have an opcode of 0x0 and a FIN bit clear,
      and the third fragment would have an opcode of 0x0 and a FIN bit
      that is set.

分片的消息由一個獨立的數據塊組成,不包含FIN標記,一個非0的操作碼,後面跟着0個或多個沒有FIN標記操作碼是0的數據塊,被一個有FIN標記操作碼是0的數據庫終結。分片的消息理論上與大的消息是一致的,大消息的負載數據是按序分片的數據塊的組合;不過在存在擴展的時候,如果擴展定義了擴展數據的解析方式,這個規則可能不適合。例如,擴展數據僅在第一個數據塊上存在,然後繼承到後續的數據塊上,或者應用在一個特殊數據塊上的擴展數據在任何一個數據塊上都有。下面的例子示範了沒有擴展數據的情況下分片如何工作。

例如:一個分成3片的文本消息,第一個數據塊中FIN爲空操作碼爲1,第二個數據塊中FIN爲空操作碼爲0,第三個數據塊中FIN不爲空操作碼爲0。


   o  Control frames (see Section 5.5) MAY be injected in the middle of
      a fragmented message.  Control frames themselves MUST NOT be
      fragmented.

控制數據包需要注入到分片消息的中間。控制數據包不能被分片。


   o  Message fragments MUST be delivered to the recipient in the order
      sent by the sender.

分片消息必須按照發送順序被提交給接收方。

   o  The fragments of one message MUST NOT be interleaved between the
      fragments of another message unless an extension has been
      negotiated that can interpret the interleaving.

一個消息的分片不能被另一個消息的分片打斷,除非定義了一個擴展支持這種打斷。


   o  An endpoint MUST be capable of handling control frames in the
      middle of a fragmented message.

接收的終端必須能從分片消息的中間處理控制數據包。


   o  A sender MAY create fragments of any size for non-control
      messages.

發送者可以爲非控制消息分任意大小的片。


   o  Clients and servers MUST support receiving both fragmented and
      unfragmented messages.

客戶端和服務端必須支持分片、非分片兩種格式的消息。


   o  As control frames cannot be fragmented, an intermediary MUST NOT
      attempt to change the fragmentation of a control frame.

由於控制數據包不能被分片,中介必須不去嘗試改變對控制數據包的分片。


   o  An intermediary MUST NOT change the fragmentation of a message if
      any reserved bit values are used and the meaning of these values
      is not known to the intermediary.

當接收的數據已經使用或不理解這些數據的含義,中介不能改變消息的分片。


   o  An intermediary MUST NOT change the fragmentation of any message
      in the context of a connection where extensions have been
      negotiated and the intermediary is not aware of the semantics of
      the negotiated extensions.  Similarly, an intermediary that didn’t
      see the WebSocket handshake (and wasn’t notified about its
      content) that resulted in a WebSocket connection MUST NOT change
      the fragmentation of any message of such connection.

在包含擴展信息的連接中,如果中介不理解擴展信息的含義,它不能改變消息的分片。簡單的說,不能識別WebSocket握手中的WebSocket連接的中介,不能改變連接中任何消息的分片。


   o  As a consequence of these rules, all fragments of a message are of
      the same type, as set by the first fragment’s opcode.  Since
      control frames cannot be fragmented, the type for all fragments in
      a message MUST be either text, binary, or one of the reserved
      opcodes.

作爲上述規則的總結,消息的所有分片的類型都一樣,等同於第一個數據塊中設置的操作碼。由於控制數據包不能分片,所有消息分片的類型必須是文本、二進制或保留的操作碼。


   NOTE: If control frames could not be interjected, the latency of a
   ping, for example, would be very long if behind a large message.
   Hence, the requirement of handling control frames in the middle of a
   fragmented message.
   IMPLEMENTATION NOTE: In the absence of any extension, a receiver
   doesn’t have to buffer the whole frame in order to process it.  For
   example, if a streaming API is used, a part of a frame can be
   delivered to the application.  However, note that this assumption
   might not hold true for all future WebSocket extensions.

注意:假如控制數據包不能被插入,在大數據的情況下ping操作的等待時間將會非常長。因此,在消息分片中間處理控制數據包是非常必要的。

5.5.  Control Frames

5.5控制數據包
   Control frames are identified by opcodes where the most significant
   bit of the opcode is 1.  Currently defined opcodes for control frames
   include 0x8 (Close), 0x9 (Ping), and 0xA (Pong).  Opcodes 0xB-0xF are
   reserved for further control frames yet to be defined.
   Control frames are used to communicate state about the WebSocket.
   Control frames can be interjected in the middle of a fragmented
   message.
   All control frames MUST have a payload length of 125 bytes or less
   and MUST NOT be fragmented.

控制數據包通過操作碼進行標記,其中最重要的操作碼是1。當前爲控制數據包定義的操作碼包括0x8(關閉)、0x9(ping)、0xA(pong)。0xB-0xF是爲將來的控制數據包預留的。控制數據包用來對WebSocket的狀態進行交互。控制數據包可以被插入到片信息的中間。所有的控制數據包的長度不能超過125字節而且不能進行分片。


5.5.1.  Close

5.5.1 關閉
   The Close frame contains an opcode of 0x8.

關閉數據包包括操作碼0x8.
   The Close frame MAY contain a body (the "Application data" portion of
   the frame) that indicates a reason for closing, such as an endpoint
   shutting down, an endpoint having received a frame too large, or an
   endpoint having received a frame that does not conform to the format
   expected by the endpoint.  If there is a body, the first two bytes of
   the body MUST be a 2-byte unsigned integer (in network byte order)
   representing a status code with value /code/ defined in Section 7.4.
   Following the 2-byte integer, the body MAY contain UTF-8-encoded data
   with value /reason/, the interpretation of which is not defined by
   this specification.  This data is not necessarily human readable but
   may be useful for debugging or passing information relevant to the
   script that opened the connection.  As the data is not guaranteed to
   be human readable, clients MUST NOT show it to end users.

關閉數據包有可能會包含主體內容(應用數據作爲數據包的一部分)解釋關閉原因,像終端關閉、終端接收到的數據太大、或者終端接收到的數據與期望的格式不一致。假如有主體內容,頭兩個字節是無符號整數,用來表示狀態碼,其值在7.4節中定義。在兩個字節後面,主體內容可能包含UTF-8編碼的數據作爲原因,這個在本文中沒有定義。這個數據不一定是人可讀的,但是對於debug或傳輸給打開連接的腳本來說可能會非常有用。由於這個數據不擔保是人可讀的,所以不能直接展示給用戶。


   Close frames sent from client to server must be masked as per
   Section 5.3.
   The application MUST NOT send any more data frames after sending a
   Close frame.
   If an endpoint receives a Close frame and did not previously send a
   Close frame, the endpoint MUST send a Close frame in response.  (When
   sending a Close frame in response, the endpoint typically echos the
   status code it received.)  It SHOULD do so as soon as practical.  An
   endpoint MAY delay sending a Close frame until its current message is
   sent (for instance, if the majority of a fragmented message is
   already sent, an endpoint MAY send the remaining fragments before
   sending a Close frame).  However, there is no guarantee that the
   endpoint that has already sent a Close frame will continue to process
   data.

從客戶端法王服務端的關閉數據包必須按照5.3節所說的進行掩碼。

應用在發送完關閉數據包後就不能再發送任何其它的數據包。

假如終端接收到了一個關閉數據包,還沒有發送過關閉數據包,這時終端必須發送一個關閉數據包作爲響應。(當發送一個關閉數據包作爲響應時,通常會把接收到的狀態碼展示出來。)它應當儘快執行。一個終端有可能拖延發送關閉數據包的時間直到當前信息發送完成(例如,假如分片信息的主體部分已經發送,終端會在發送關閉數據包前發送剩餘的數據包)。然而,無法保證一個終端在發送完關閉數據包後會繼續處理數據。

   After both sending and receiving a Close message, an endpoint
   considers the WebSocket connection closed and MUST close the
   underlying TCP connection.  The server MUST close the underlying TCP
   connection immediately; the client SHOULD wait for the server to
   close the connection but MAY close the connection at any time after
   sending and receiving a Close message, e.g., if it has not received a
   TCP Close from the server in a reasonable time period.
   If a client and server both send a Close message at the same time,
   both endpoints will have sent and received a Close message and should
   consider the WebSocket connection closed and close the underlying TCP
   connection.

在發送和接收錯誤信息之後,終端認爲WebSocket連接已經關閉,然後必須關閉底層的TCP連接。服務端必須立即停止底層的TCP連接;客戶端應該等待服務端去關閉連接但是有可能在發送並接收到關閉數據包後關閉連接,例如,當它在一個合理的時間內沒有接收到服務端的TCP關閉信息時。假如客戶端和服務端同時發送了關閉信息,它們已經發送和接收了關閉信息,應當認定WebSocket連接已經關閉並關閉底層的TCP連接。
5.5.2.  Ping
   The Ping frame contains an opcode of 0x9.
   A Ping frame MAY include "Application data".
   Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in
   response, unless it already received a Close frame.  It SHOULD
   respond with Pong frame as soon as is practical.  Pong frames are
   discussed in Section 5.5.3.
   An endpoint MAY send a Ping frame any time after the connection is
   established and before the connection is closed.
   NOTE: A Ping frame may serve either as a keepalive or as a means to
   verify that the remote endpoint is still responsive.

5.5.2 ping

Ping數據包包含狀態碼0x9.

Ping數據包可能包含應用數據。

一旦接收到Ping數據包,終端必須迴應一個Pong數據包,除非它已經接收到了關閉數據包。它應該儘快地返回一個Pong數據包。Pong數據包在5.5.3中描述。

連接建立後關閉前,一個終端有可能在任何時間發送Ping數據包。

注意:Ping數據包一般作爲判斷遠程終端是否保持活躍或者是否依舊響應的方式。
5.5.3.  Pong
   The Pong frame contains an opcode of 0xA.
   Section 5.5.2 details requirements that apply to both Ping and Pong
   frames.
   A Pong frame sent in response to a Ping frame must have identical
   "Application data" as found in the message body of the Ping frame
   being replied to.
   If an endpoint receives a Ping frame and has not yet sent Pong
   frame(s) in response to previous Ping frame(s), the endpoint MAY
   elect to send a Pong frame for only the most recently processed Ping
   frame.

   A Pong frame MAY be sent unsolicited.  This serves as a
   unidirectional heartbeat.  A response to an unsolicited Pong frame is
   not expected.

5.5.3 Pong

Pong數據包包含操作碼 0xA.

5.5.2節介紹了Ping和Pong數據包的應用的重要性。

在響應中作爲Ping數據包的迴應的Pong數據包,必須包含Ping數據包消息體中的應用數據。

假如一個終端接收到了Ping數據包但是還沒有發送Pong數據包作爲響應,終端可以選擇爲最近收到的Ping數據包發送Pong數據包。

一個Pong數據包有可能是不請自來,這個會作爲一個單向的心跳。對於主動的Pong數據包不需要發送響應。


5.6.  Data Frames

5.6 數據包
   Data frames (e.g., non-control frames) are identified by opcodes
   where the most significant bit of the opcode is 0.  Currently defined
   opcodes for data frames include 0x1 (Text), 0x2 (Binary).  Opcodes
   0x3-0x7 are reserved for further non-control frames yet to be
   defined.

數據包(像非控制數據包)通過操作碼標記,其中操作碼最重要的位是0。當前爲數據包定義的狀態碼包括0x1(文本),0x2(二進制)。狀態碼0x3-0x7是爲將來的非控制數據包預留的。
   Data frames carry application-layer and/or extension-layer data.  The
   opcode determines the interpretation of the data:
   Text
      The "Payload data" is text data encoded as UTF-8.  Note that a
      particular text frame might include a partial UTF-8 sequence;
      however, the whole message MUST contain valid UTF-8.  Invalid
      UTF-8 in reassembled messages is handled as described in
      Section 8.1.
   Binary
      The "Payload data" is arbitrary binary data whose interpretation
      is solely up to the application layer.

數據包承載應用層或擴展層的數據。操作碼決定了數據的解析方式。

Text:

負載數據是經過UTF-8編碼的文本。需要注意一個特殊的文本數據包可能包含一個特殊的UTF-8序列。當然,整個序列必須包含合法的UTF-8。在重組後的信息中的非法的消息會按8.1節所說的處理。

Binary:負載數據是任意二進制,解析方式由應用層決定。


5.7.  Examples

5.7 例子
   o  A single-frame unmasked text message

      *  0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f (contains "Hello")
   o  A single-frame masked text message
      *  0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58
         (contains "Hello")
   o  A fragmented unmasked text message
      *  0x01 0x03 0x48 0x65 0x6c (contains "Hel")
      *  0x80 0x02 0x6c 0x6f (contains "lo")

   o  Unmasked Ping request and masked Ping response
      *  0x89 0x05 0x48 0x65 0x6c 0x6c 0x6f (contains a body of "Hello",
         but the contents of the body are arbitrary)
      *  0x8a 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58
         (contains a body of "Hello", matching the body of the ping)
   o  256 bytes binary message in a single unmasked frame
      *  0x82 0x7E 0x0100 [256 bytes of binary data]
   o  64KiB binary message in a single unmasked frame
      *  0x82 0x7F 0x0000000000010000 [65536 bytes of binary data]

o A single-frame unmasked text message

一個單獨的未經過掩碼的文本數據

* 0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f (contains "Hello")
o A single-frame masked text message

一個單獨的經過掩碼的文本數據
* 0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58
(contains "Hello")
o A fragmented unmasked text message

一個分片的未掩碼的文本數據。
* 0x01 0x03 0x48 0x65 0x6c (contains "Hel")
* 0x80 0x02 0x6c 0x6f (contains "lo")

o Unmasked Ping request and masked Ping response

一個未掩碼的ping請求和一個掩碼的ping響應。
* 0x89 0x05 0x48 0x65 0x6c 0x6c 0x6f (contains a body of "Hello",
but the contents of the body are arbitrary)
* 0x8a 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58
(contains a body of "Hello", matching the body of the ping)
o 256 bytes binary message in a single unmasked frame

256字節二進制信息,在一個單獨的未掩碼數據包中。
* 0x82 0x7E 0x0100 [256 bytes of binary data]
o 64KiB binary message in a single unmasked frame

64字節二進制數據,在一個單獨的未掩碼數據包中。
* 0x82 0x7F 0x0000000000010000 [65536 bytes of binary data]


5.8.  Extensibility

5.8 擴展性
   The protocol is designed to allow for extensions, which will add
   capabilities to the base protocol.  The endpoints of a connection
   MUST negotiate the use of any extensions during the opening
   handshake.  This specification provides opcodes 0x3 through 0x7 and
   0xB through 0xF, the "Extension data" field, and the frame-rsv1,
   frame-rsv2, and frame-rsv3 bits of the frame header for use by
   extensions.  The negotiation of extensions is discussed in further
   detail in Section 9.1.  Below are some anticipated uses of
   extensions.  This list is neither complete nor prescriptive.

該協議被設計成可以進行擴展,這些擴展會增強基礎協議的能力。連接的終端必須在打開握手的時候必須能識別所有的擴展。該說明書提供了從0x-3到0x-7、從0x-B到0x-F的操作碼,Extension data字段,數據包結構中的frame-rsv1、frame-rsv2、frame-rsv3作爲擴展使用。擴展信息如何識別在後面的9.1節中詳細討論。下面是對擴展信息的推薦使用。下面這個列表既不完整也不規範。
   o  "Extension data" may be placed in the "Payload data" before the
      "Application data".

擴展信息可能被放在應用數據的前面。
   o  Reserved bits can be allocated for per-frame needs.

保留位可根據每個數據包的需求分配。
   o  Reserved opcode values can be defined.

保留操作碼的值可以定義。
   o  Reserved bits can be allocated to the opcode field if more opcode
      values are needed.

如果需要更多的操作碼,可以把保留位分配給操作碼。
   o  A reserved bit or an "extension" opcode can be defined that
      allocates additional bits out of the "Payload data" to define
      larger opcodes or more per-frame bits.

爲了給每個數據包定義更大更到的操作碼,一個保留位或擴展信息的保留操作碼可以定義成這樣:分配負載數據之外的位數。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章