-
Notifications
You must be signed in to change notification settings - Fork 0
WebSocket
wknet::websocket 提供 ws / wss 客户端。wss 默认经 TLS ALPN h2,http/1.1 协商,优先 RFC 8441 extended CONNECT over HTTP/2;失败则 Auto 回落 HTTP/1.1 Upgrade。ws:// 不隐式 h2c。
API 签名见 WebSocket API;HTTP/2 隧道原语见 HTTP/2。
| 主题 | 行为 |
|---|---|
| 传输 |
TransportMode::Auto(默认);Http11Only 强制 H1 Upgrade |
wss |
默认 offer h2,http/1.1;h2 + ENABLE_CONNECT_PROTOCOL → RFC 8441 |
| 分片发送 |
Send*Ex + FinalFragment=false / SendContinuation
|
| 分片接收 | 默认聚合完整消息;DeliverFragments=true 按 wire 交付 |
| permessage-deflate | opt-in;默认关;未请求扩展一律拒绝 |
| Close | 主动发 close 后等 peer(3s);被动 echo 后关 transport |
Message.Data |
指向内部缓冲;下次 Receive / Close 前有效 |
wknet::websocket::ConnectConfig cfg = wknet::websocket::DefaultConnectConfig();
cfg.Url = "wss://echo.example/ws";
cfg.UrlLength = 21;
// cfg.TransportMode = wknet::http::WebSocketTransportMode::Http11Only;
// cfg.PerMessageDeflate.Enable = true;
wknet::websocket::WebSocket* ws = nullptr;
wknet::websocket::ConnectEx(session, &cfg, &ws);-
ConnectConfig.Headers可带Origin/Authorization/Cookie等。 -
库受控头被拒:
Host、Connection、Upgrade、Content-Length、Transfer-Encoding、全部Sec-WebSocket-*。 -
Sec-WebSocket-Accept常量时间比对;子协议须为已请求之一。 - 默认不跟随 opening-handshake 的 3xx / 401 / 407:返回
STATUS_NOT_SUPPORTED并保留状态码;其它非 101 →STATUS_INVALID_NETWORK_RESPONSE。 - 解析 ≤8 地址逐个尝试;取消令牌贯穿;同步路径
PASSIVE_LEVEL。
| 传输 | 掩码 |
|---|---|
| HTTP/1.1 Upgrade | 客户端帧始终掩码(每帧新随机键) |
| RFC 8441 over H2 | 按规范无掩码 DATA 隧道 |
| 收到被掩码的服务端帧 | 协议错误 → close 1002 |
-
SendText/SendBinary默认整消息、FinalFragment=true。 -
*Ex设FinalFragment=false开启分片;后续用SendContinuation/SendContinuationEx。 - 库按帧缓冲自动切块:首帧真实 opcode,后续 Continuation。
- 文本消息跨分片增量 UTF-8 校验;最终片不完整码点 →
STATUS_INVALID_PARAMETER。
DeliverFragments |
交付形态 |
|---|---|
false(默认) |
客户端重组完整消息;FinalFragment=true
|
true |
按 wire:首帧 Text/Binary,续帧 Continuation;FinalFragment = 真实 FIN |
文本仍跨片 UTF-8 校验;最终片非法 → close 1007 / STATUS_INVALID_NETWORK_RESPONSE。
Message.Data / DataLength 指向库内缓冲,在同句柄下一次成功 Receive 或 Close 之前可读。需要跨调用保留时请自行拷贝。
- 开启:
ConnectConfig.PerMessageDeflate.Enable=true。 - 可配
ClientNoContextTakeover/ServerNoContextTakeover/ClientMaxWindowBits/ServerMaxWindowBits(仅8..15)。 - H1 Upgrade 与 RFC 8441 共用同一 offer/校验路径;调用方不得手写
Sec-WebSocket-Extensions。 - 发送:仅压缩 Text/Binary 首片设 RSV1;Continuation / 控制帧不设 RSV1。
- 接收:未协商、控制帧、Continuation 上的 RSV1 → 协议错误关闭。
- 解压受
MaxMessageBytes、输出容量与膨胀比限制;不协商 permessage-deflate 以外的 WebSocket 扩展。
| 事件 | 处理 |
|---|---|
| Ping |
AutoReplyPing 默认开 → 自动 Pong |
| 单次接收控制帧 >100 | close 1008 |
| 被掩码帧 / 分片状态错 | close 1002 |
| 非法 UTF-8(文本/close) | close 1007 |
超 MaxMessageBytes
|
close 1009(STATUS_BUFFER_TOO_SMALL) |
合法入站 close 码:1000–1014(除 1004/1005/1006)或 3000–4999;长度恰为 1 的 close payload → 协议错误。
Close 时序
-
主动
Close/CloseEx:发 close(CloseExreason ≤123 字节)→ 等待 peer close(默认 3s;超时/终止吞为成功)→ 关 transport。 - 被动:收到 peer close → echo → 关 transport。
-
并发约束:
Close不得与同句柄「新 I/O 发起」并发;最安全为单线程 连接→发→收→关。
wknet::websocket is the ws / wss client. For wss, TLS ALPN defaults to h2,http/1.1 and prefers RFC 8441 extended CONNECT over HTTP/2; Auto falls back to HTTP/1.1 Upgrade when that path is unavailable. ws:// does not implicitly use h2c.
API signatures: WebSocket API. HTTP/2 tunnel primitive: HTTP/2.
| Topic | Behavior |
|---|---|
| Transport |
TransportMode::Auto (default); Http11Only forces H1 Upgrade |
wss |
Offers h2,http/1.1 by default; h2 + ENABLE_CONNECT_PROTOCOL → RFC 8441 |
| Fragmented send |
Send*Ex + FinalFragment=false / SendContinuation
|
| Fragmented receive | Default: reassemble whole messages; DeliverFragments=true for wire fragments |
| permessage-deflate | Opt-in; off by default; unrequested extensions rejected |
| Close | Active: send close then wait (3s); passive: echo then close transport |
Message.Data |
Points at an internal buffer; valid until the next Receive / Close |
wknet::websocket::ConnectConfig cfg = wknet::websocket::DefaultConnectConfig();
cfg.Url = "wss://echo.example/ws";
cfg.UrlLength = 21;
// cfg.TransportMode = wknet::http::WebSocketTransportMode::Http11Only;
// cfg.PerMessageDeflate.Enable = true;
wknet::websocket::WebSocket* ws = nullptr;
wknet::websocket::ConnectEx(session, &cfg, &ws);-
ConnectConfig.Headersmay carryOrigin/Authorization/Cookie, etc. -
Library-controlled headers are rejected:
Host,Connection,Upgrade,Content-Length,Transfer-Encoding, allSec-WebSocket-*. -
Sec-WebSocket-Acceptis compared in constant time; the selected subprotocol must be one that was offered. - Opening-handshake 3xx / 401 / 407 are not followed by default:
STATUS_NOT_SUPPORTEDwith the status preserved; other non-101 →STATUS_INVALID_NETWORK_RESPONSE. - Up to 8 resolved addresses are tried; cancellation tokens apply end-to-end; sync paths require
PASSIVE_LEVEL.
| Transport | Masking |
|---|---|
| HTTP/1.1 Upgrade | Client frames are always masked (fresh key per frame) |
| RFC 8441 over H2 | Unmasked DATA tunnel per the RFC |
| Masked server frame | Protocol error → close 1002 |
-
SendText/SendBinarydefault to whole messages withFinalFragment=true. - Set
FinalFragment=falseon*Exto start a fragmented message; continue withSendContinuation/SendContinuationEx. - The library auto-chunks to the frame buffer: first frame uses the real opcode, later frames use Continuation.
- Text is validated with incremental cross-fragment UTF-8; an unfinished code point on the final fragment →
STATUS_INVALID_PARAMETER.
DeliverFragments |
Delivery |
|---|---|
false (default) |
Client-reassembled complete message; FinalFragment=true
|
true |
Wire fragments: first Text/Binary, then Continuation; FinalFragment = real FIN |
Text still uses cross-fragment UTF-8 validation; a bad final fragment closes with 1007 / STATUS_INVALID_NETWORK_RESPONSE.
Message.Data / DataLength refer to a library buffer readable until the next successful Receive or Close on the same handle. Copy the bytes if you need them longer.
- Enable with
ConnectConfig.PerMessageDeflate.Enable=true. - Configurable:
ClientNoContextTakeover/ServerNoContextTakeover/ClientMaxWindowBits/ServerMaxWindowBits(only8..15). - H1 Upgrade and RFC 8441 share the same offer/validation path; callers must not hand-write
Sec-WebSocket-Extensions. - Send sets RSV1 only on the first compressed Text/Binary fragment; continuations and control frames never set RSV1.
- Receive treats RSV1 on unnegotiated links, control frames, or continuations as a protocol error and closes.
- Inflate is bounded by
MaxMessageBytes, output capacity, and expansion ratio. WebSocket extensions other than permessage-deflate are not negotiated.
| Event | Handling |
|---|---|
| Ping |
AutoReplyPing defaults on → automatic Pong |
| >100 control frames per receive | close 1008 |
| Masked frame / bad fragment state | close 1002 |
| Illegal UTF-8 (text/close) | close 1007 |
Over MaxMessageBytes
|
close 1009 (STATUS_BUFFER_TOO_SMALL) |
Valid inbound close codes: 1000–1014 (except 1004/1005/1006) or 3000–4999; a close payload of length exactly 1 is a protocol error.
Close sequencing
-
Active
Close/CloseEx: send close (CloseExreason ≤123 bytes) → wait for peer close (default 3s; timeout/termination swallowed as success) → close transport. - Passive: receive peer close → echo → close transport.
-
Concurrency: never start new I/O on the same handle concurrently with
Close; safest pattern is single-threaded connect→send→receive→close.
- No compression by default; no default handshake redirect / 401/407 following.
- WebSocket over HTTP/3 is not supported (see HTTP/3).
- See the capability matrix for support scope.
-
开始使用 / Get Started
-
概念与行为 / Concepts
-
协议指南 / Protocols
-
API 参考 / API Reference
-
贡献与项目 / Contribute