websocket 子包将 message-oriented WebSocket 连接适配为 yamux 所需的可靠有序字节流连接,保持 core yamux 包本身不引入任何第三方 WebSocket 依赖。
binary frame,防止 text/binary 混用破坏协议边界NextReader / NextWriter 风格接口的库配合┌─────────────────────────────────────────────────────────────┐ │ yamux.Session (core) │ │ │ │ │ net.Conn 接口 │ │ │ │ │ ┌──────────┴──────────┐ │ │ │ websocket.Conn │ ← 本适配器 │ │ │ (net.Conn) │ │ │ └──────────┬──────────┘ │ │ │ │ │ ┌──────────┴──────────┐ │ │ │ FramedConn │ ← 底层 WebSocket │ │ │ NextReader/Writer │ │ │ └─────────────────────┘ │ └─────────────────────────────────────────────────────────────┘
适配器将每个 binary/text message 视为连续字节流片段:
go get cnb.cool/zishuo/yamux/websocket
import (
"cnb.cool/zishuo/yamux"
"cnb.cool/zishuo/yamux/websocket"
)
// 1. 通过适配器创建 net.Conn
wsConn, err := websocket.NewConn(rawWSConn, nil)
if err != nil {
return err
}
// 2. 创建 yamux session(与 TCP transport 完全一致)
session, err := yamux.Client(wsConn, nil)
if err != nil {
return err
}
defer session.Close()
也可以直接使用子包提供的辅助函数,一步到位创建 session:
// 创建 Client session
session, err := websocket.Client(rawWSConn, nil, nil)
if err != nil {
return err
}
defer session.Close()
// 创建 Server session
session, err := websocket.Server(rawWSConn, nil, nil)
if err != nil {
return err
}
defer session.Close()
当连接需要穿越对 idle 敏感的代理或负载均衡器时,可启用 transport 级 Ping:
cfg := &websocket.Config{
PingInterval: 30 * time.Second,
PingTimeout: 10 * time.Second,
}
wsConn, err := websocket.NewConn(rawWSConn, cfg)
if err != nil {
return err
}
底层 WebSocket 连接需要满足最小接口 FramedConn:
type FramedConn interface {
NextReader() (messageType int, r io.Reader, err error)
NextWriter(messageType int) (io.WriteCloser, error)
Close() error
}
若底层连接还实现了以下可选接口,适配器会自动增强对应能力:
| 可选接口 | 能力增强 |
|---|---|
WriteControl(int, []byte, time.Time) error | 支持 transport 级 Ping/Pong |
SetReadDeadline(time.Time) error | 支持读 deadline 透传 |
SetWriteDeadline(time.Time) error | 支持写 deadline 透传 |
LocalAddr() net.Addr / RemoteAddr() net.Addr | 直接暴露地址 |
UnderlyingConn() net.Conn | 透透底层 net.Conn 的地址信息 |
type Config struct {
// AcceptTextMessages 允许把 text frame 也当作有序字节流的一部分读取。
// 默认 false;用于承载 yamux 协议负载时通常应保持 false。
AcceptTextMessages bool
// PingInterval 控制 transport 级 Ping 频率。
// 默认 0(关闭);当连接需要穿越对 idle 敏感的 proxy / LB 时可启用。
PingInterval time.Duration
// PingTimeout 控制单次 transport Ping 的写超时。
// 仅在 PingInterval > 0 时生效;默认 10s。
PingTimeout time.Duration
}
默认值:
AcceptTextMessages = falsePingInterval = 0PingTimeout = 10svar (
// 传入的连接为 nil 或不可用
ErrInvalidConnection = fmt.Errorf("invalid nil websocket connection")
// 启用了 Ping,但底层连接不支持 WriteControl
ErrPingUnsupported = fmt.Errorf("websocket ping requires WriteControl support")
)
// 收到不符合配置约束的 message type
type ErrUnexpectedMessageType struct {
MessageType int
}
生产建议:
ErrUnexpectedMessageType 通常意味着对端发送了错误的 frame 类型,建议记录后关闭连接ErrPingUnsupported 在配置校验阶段即返回,可在启动时断言yamux.Config 配置 keepalive、timeout、flow-control,transport adapter 仅解决字节流适配问题SetReadDeadline / SetWriteDeadline,adapter 只能在操作开始前检查 deadline 是否已过期,无法强制打断底层阻塞 I/O