zoukankan      html  css  js  c++  java
  • WebSocket协议分析

    内容不断更新,目前包括协议中握手和数据帧的分析

     

    1.1 背景

    1.2 协议概览

    协议包含两部分:握手,数据传输。

    客户端的握手如下:
    GET /chat HTTP/1.1
    Host: server.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
    Origin: http://example.com
    Sec-WebSocket-Protocol: chat, superchat
    Sec-WebSocket-Version: 13

    服务端的握手如下:
    HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat
    客户端和服务端都发送了握手,并且成功,数据传输即可开始。
     
    1.3 发起握手
    发起握手是为了兼容基于HTTP的服务端程序,这样一个端口可以同时处理HTTP客户端和WebSocket客户端
    因此WebSocket客户端握手是一个HTTP Upgrade请求:
    GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13
    握手中的域的顺序是任意的。
     
    5 数据帧
    5.1 概述
    WebScoket协议中,数据以帧序列的形式传输。
    考虑到数据安全性,客户端向服务器传输的数据帧必须进行掩码处理。服务器若接收到未经过掩码处理的数据帧,则必须主动关闭连接。
    服务器向客户端传输的数据帧一定不能进行掩码处理。客户端若接收到经过掩码处理的数据帧,则必须主动关闭连接。
    针对上情况,发现错误的一方可向对方发送close帧(状态码是1002,表示协议错误),以关闭连接。
    5.2 帧协议
    WebSocket数据帧结构如下图所示:
          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位
    表示这是消息的最后一帧(结束帧),一个消息由一个或多个数据帧构成。若消息由一帧构成,起始帧即结束帧。
     
    RSV1,RSV2,RSV3:各1位
    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_.
    这里我翻译不好,大致意思是如果未定义扩展,各位是0;如果定义了扩展,即为非0值。如果接收的帧此处非0,扩展中却没有该值的定义,那么关闭连接。
     
    OPCODE:4位
    解释PayloadData,如果接收到未知的opcode,接收端必须关闭连接。
    0x0表示附加数据帧
    0x1表示文本数据帧
    0x2表示二进制数据帧
    0x3-7暂时无定义,为以后的非控制帧保留
    0x8表示连接关闭
    0x9表示ping
    0xA表示pong
    0xB-F暂时无定义,为以后的控制帧保留
     
    MASK:1位
    用于标识PayloadData是否经过掩码处理。如果是1,Masking-key域的数据即是掩码密钥,用于解码PayloadData。客户端发出的数据帧需要进行掩码处理,所以此位是1。
     
    Payload length:7位,7+16位,7+64位
    PayloadData的长度(以字节为单位)。
    如果其值在0-125,则是payload的真实长度。
    如果值是126,则后面2个字节形成的16位无符号整型数的值是payload的真实长度。注意,网络字节序,需要转换。
    如果值是127,则后面8个字节形成的64位无符号整型数的值是payload的真实长度。注意,网络字节序,需要转换。
    长度表示遵循一个原则,用最少的字节表示长度(我理解是尽量减少不必要的传输)。举例说,payload真实长度是124,在0-125之间,必须用前7位表示;不允许长度1是126或127,然后长度2是124,这样违反原则。
    Payload长度是ExtensionData长度与ApplicationData长度之和。ExtensionData长度可能是0,这种情况下,Payload长度即是ApplicationData长度。
     
     
    WebSocket协议规定数据通过帧序列传输。
    客户端必须对其发送到服务器的所有帧进行掩码处理。
    服务器一旦收到无掩码帧,将关闭连接。服务器可能发送一个状态码是1002(表示协议错误)的Close帧。
    而服务器发送客户端的数据帧不做掩码处理,一旦客户端发现经过掩码处理的帧,将关闭连接。客户端可能使用状态码1002。
     

    消息分片

    分片目的是发送长度未知的消息。如果不分片发送,即一帧,就需要缓存整个消息,计算其长度,构建frame并发送;使用分片的话,可使用一个大小合适的buffer,用消息内容填充buffer,填满即发送出去。

    分片规则:

    1.一个未分片的消息只有一帧(FIN为1,opcode非0)

    2.一个分片的消息由起始帧(FIN为0,opcode非0),若干(0个或多个)帧(FIN为0,opcode为0),结束帧(FIN为1,opcode为0)。

    3.控制帧可以出现在分片消息中间,但控制帧本身不允许分片。

    4.分片消息必须按次序逐帧发送。

    5.如果未协商扩展的情况下,两个分片消息的帧之间不允许交错。

    6.能够处理存在于分片消息帧之间的控制帧

    7.发送端为非控制消息构建长度任意的分片

    8.client和server兼容接收分片消息与非分片消息

    9.控制帧不允许分片,中间媒介不允许改变分片结构(即为控制帧分片)

    10.如果使用保留位,中间媒介不知道其值表示的含义,那么中间媒介不允许改变消息的分片结构

    11.如果协商扩展,中间媒介不知道,那么中间媒介不允许改变消息的分片结构,同样地,如果中间媒介不了解一个连接的握手信息,也不允许改变该连接的消息的分片结构

    12.由于上述规则,一个消息的所有分片是同一数据类型(由第一个分片的opcode定义)的数据。因为控制帧不允许分片,所以一个消息的所有分片的数据类型是文本、二进制、opcode保留类型中的一种。

    需要注意的是,如果控制帧不允许夹杂在一个消息的分片之间,延迟会较大,比如说当前正在传输一个较大的消息,此时的ping必须等待消息传输完成,才能发送出去,会导致较大的延迟。为了避免类似问题,需要允许控制帧夹杂在消息分片之间。

    控制帧

     

    根据官方文档整理,官方文档参考http://datatracker.ietf.org/doc/rfc6455/?include_text=1

  • 相关阅读:
    POJ 2723 Get Luffy Out(2-SAT)
    ZOJ 3613 Wormhole Transport
    HDU 4085 Peach Blossom Spring
    NBUT 1221 Intermediary
    NBUT 1223 Friends number
    NBUT 1220 SPY
    NBUT 1218 You are my brother
    PAT 1131. Subway Map (30)
    ZSTU OJ 4273 玩具
    ZSTU OJ 4272 最佳淘汰算法
  • 原文地址:https://www.cnblogs.com/caosiyang/p/2637721.html
Copyright © 2011-2022 走看看