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.

为了给每个数据包定义更大更到的操作码,一个保留位或扩展信息的保留操作码可以定义成这样:分配负载数据之外的位数。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章