Websocket笔记
文章目录
标准
RFC6455 https://datatracker.ietf.org/doc/html/rfc6455
握手请求
REQ
http
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
字段含义
GET /chat HTTP/1.1
GET: HTTP 请求方法,用于获取资源。在 WebSocket 握手中,这个方法用于发起连接请求。
/chat: 请求的路径。
HTTP/1.1: 使用的 HTTP 版本,通常是 1.1。
Host: server.example.com
指定请求的目标服务器主机名和端口号。这个字段是 HTTP/1.1 的标准要求,表示目标服务器的域名。
Upgrade: websocket
表示客户端希望将当前的 HTTP 连接升级为 WebSocket 连接。
Connection: Upgrade
表示连接应该升级。这个字段配合 Upgrade 字段使用。
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
一个 16 字节的随机 Base64 编码的字符串,由客户端生成。用于安全验证,防止不正当的 WebSocket 连接。
Sec-WebSocket-Version: 13
指定 WebSocket 协议的版本。当前规范中,13 是唯一合法值(定义在 RFC 6455 中)。
Origin: http://example.com
指示 WebSocket 请求的来源。服务器可以使用这个字段来检查请求是否来自允许的来源,以防止跨站点 WebSocket 攻击(CSWSH)。这个字段在浏览器环境中是强制性的。
Sec-WebSocket-Protocol: chat, superchat
可选字段,表示客户端支持的子协议。子协议是在 WebSocket 连接上进行特定类型的通信协议,比如聊天、流媒体等。服务器会在响应中选择一个协议,或者忽略这个字段。
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
可选字段,用于指定 WebSocket 扩展。扩展功能可以优化或增强 WebSocket 的通信能力,例如压缩消息等。服务器可以在响应中确认支持的扩展。
RES
http
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
服务器响应字段含义
HTTP/1.1 101 Switching Protocols
表示服务器接受了协议升级请求,并切换到 WebSocket 协议。
Upgrade: websocket
表示服务器同意升级到 WebSocket 协议。
Connection: Upgrade
表示连接已升级。
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
服务器基于客户端发送的 Sec-WebSocket-Key 计算出的 Base64 编码字符串,用于确认握手的有效性。
Sec-WebSocket-Protocol: chat
如果客户端请求了多个子协议,服务器会在此字段中返回所选的协议。
Sec-WebSocket-Extensions: permessage-deflate
返回服务器支持的扩展。
数据帧格式
text
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)
FIN (Final frame):指示该帧是否是消息的最后一帧。
1 表示这是消息的最后一帧。
0 表示后面还有更多帧属于同一消息。 - RSV1, RSV2, RSV3 (各 1 bit)
这三个保留位(Reserved bits)通常设置为 0,除非某些扩展定义了这些位的用途。
如果未使用扩展,服务器和客户端必须忽略这三个位。 - Opcode (4 bits)
操作码:指定帧的类型,定义了该帧携带的负载数据的解释方式。
常用操作码:
0x0:连续帧(Continuation frame)
0x1:文本帧(Text frame)
0x2:二进制帧(Binary frame)
0x8:连接关闭帧(Connection close frame)
0x9:Ping 帧(Ping frame)
0xA:Pong 帧(Pong frame)
其他值保留用于未来定义。 - MASK (1 bit)
掩码标志:指示是否对负载数据进行了掩码处理。
1 表示负载数据已被掩码处理。
0 表示负载数据未被掩码处理。
从客户端发送到服务器的帧必须设置掩码标志,服务器到客户端的帧则通常不需要。 - Payload length (7 bits, 7+16 bits, or 7+64 bits)
负载长度:表示负载数据的长度。
0-125:负载数据的实际长度。
126:负载长度为 16 位,后面的 16 位字段用于表示长度(最大值为 65535)。
127:负载长度为 64 位,后面的 64 位字段用于表示长度(最大值为 2^63-1)。 - Extended payload length (16 bits or 64 bits)
扩展负载长度:如果负载长度字段的值为 126 或 127,则此部分用于表示实际的负载数据长度。
126:16 位(2 字节)扩展负载长度字段。
127:64 位(8 字节)扩展负载长度字段。 - Masking-key (32 bits)
掩码键:如果掩码标志位为 1,这个字段包含了 4 字节的掩码键。
客户端发送给服务器的帧必须包含掩码键,服务器会使用该键对数据进行解码。 - Payload Data (x+y bits)
负载数据:实际传输的数据内容。
如果使用了掩码处理,负载数据必须先通过掩码键解码。
负载数据的长度由前面的 Payload length 和 Extended payload length 字段确定。 - Payload Data Continued
如果负载数据非常长,它可能会跨越多个帧。
如果 FIN 位设置为 0,表示后续还有数据帧,它们将与当前帧的负载数据组合形成完整消息。