WebSocket-Learning-1

WebSocket

1.什么是WebSocket

WebSocket 是一种通讯协议,目标就是替代XmlHttpRequest 和长期轮询的解决方案。应用在实时弹幕、消息推送、棋牌游戏、聊天等需要及时通讯的场景。

2.WebSocket 连接有两个阶段

握手(handshake)和数据传输(data transfer)

3.客户端发送握手请求
  • Uri 格式
    ws-URI=ws://host[:port]path[?query]
    例如:ws://localhost:10020/
  • 在与服务端建立连接时,客户端必须发送握手请求,请求是一个http升级协议(Upgrade)请求。并且该请求必须满足:
    (1) 握手请求必须是一个正常的HTTP请求。
    (2) 请求方法必须为GET,并且HTTP协议最低为1.1
    (3)请求头必须包含Host
    (4)请求头必须包含Upgrade,并且值为websocket
    (5)请求头必须包含Connection,并且值为Upgrade
    (6)请求头必须包含Sec-WebSocket-Key,值为经过Base64转换的长度为16字节的一组数据
    (7)请求头必须包含Origin,如果客户端是浏览器这个值肯定是有的,如果非浏览器的客户端,这个值可以随意改。
    (8)请求头必须包含Sec-WebSocket-Version,并且值为13
    (9)请求头可以带一个Sec-WebSocket-Protocol,这个值告诉服务端客户端想用的子协议,多个用逗号分开
    (10)请求头可以带一个Sec-WebSocket-Extensions,这个值告诉服务端客户端支持的协议级别的扩展。
    (11)请求头可以带一个和权限校验相关的头,例如Cookie,Authentication等
  • 示例:

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

如果握手成功的话,服务器回应

 HTTP/1.1 101 Switching Protocols
 Upgrade: websocket
 Connection: Upgrade
 Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
 Sec-WebSocket-Protocol: chat

当客户端将握手请求发出去之后,就要等待服务端的响应。当服务端响应成功之后,客户端还需要做如下校验

  1. 返回的响应码非101,例如401,500,403,503 等等,客户端连接失败
  2. 返回的响应头部不包含Upgrade或者Upgrade的值不是websocket,客户端连接失败
  3. 返回的响应头部不包含Connection或者Connection的值不是Upgrade,客户端连接失败
  4. 返回的响应头部不包含Sec-WebSocket-Accept或者Sec-WebSocket-Accept的值并不是Base64(SHA1(Sec-WebSocket-Key+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11")),客户端连接失败
  5. 返回的响应头部Sec-WebSocket-Extensions中的值并不是客户端发送的Sec-WebSocket-Extensions中的值,客户端连接失败
  6. 返回的响应头部Sec-WebSocket-Protocol中的值并不是客户端发送的Sec-WebSocket-Protocol中的值,客户端连接失败
服务端接收握手请求

如果服务端在处理请求过程中不满足以下任何一项,服务端都会终止处理该请求

  1. 必须是HTTP1.1+的GET请求
  2. 包含Host请求头
  3. 包含Upgrade值为WebSocket的请求头
  4. 包含Connection值为Upgrade的请求头
  5. 包含Sec-WebSocket-Key值为16字节长度的Base64字符串
  6. 包含Sec-WebSocket-Version值为13的请求头
  7. 非必须:Origin
  8. 非必须:Sec-WebSocket-Protocol
  9. 非必须:Sec-WebSocket-Extensions

当服务端确定这是一个正常的握手请求并且愿意处理此请求,那么服务端需要回应一个HTTP响应:

  1. 状态码必须为 101 Switching Protocol
  2. Upgrade:WebSocket
  3. Connection:Upgrade
  4. Sec-WebSocket-Accept,如上文所说,值为:Base64(SHA1(Sec-WebSocket-Key+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))
  5. Sec-WebSocket-Protocol,根据客户端传的值
  6. Sec-WebSocket-Extensions,根据客户端传的值
    至此,握手结束。连接状态由CONNECTING进入OPEN状态
协议帧

WebSocket的协议帧格式如下:
WebSocket协议

FIN 1bit
包结束标志,1 代表最后一个消息包,0代表某一段消息包
RSV1, RSV2, RSV3: 每个1bit,共3bit
值为0,除非协议扩展(Extensions)声明了非0的值的含义。如果服务端收到非0的值,并且没有相应的定义,那么服务端将直接终止连接。
Opcode 4bit
x0 后续帧
x1 文本帧
x2 二进制帧
x3-X7 非控制帧预留
x8 关闭连接
x9 PING
xA PONG
xB-xF 控制帧预留
Mask 1 bit 是否掩码。客户端向服务器发送,必须掩码。服务端向客户端发送不需掩码
PayLoad Length 7bits,7+16bits,7+64bits,如果值为 0-125,则数据包长度为0-125.如果值为126,则后2个字节为数据包长度:16bit。如果值为127,则后8个字节为数据包长度:64bit。
Masking-Key, 0-4bits.是否有值取决于 Mask 标识位是否为1.
Extension data X bytes 如果在握手时协商了扩展,会有值,否则为0
Application data y bytes 剩余消息包
PayLoad data (x+y)bytes 总消息包=Extension data + Application data.如果有掩码,解码公式如下:

posted @ 2023-06-03 10:05  丹心石  阅读(40)  评论(0编辑  收藏  举报