# wsc WebSocket 服务端框架 + 配套客户端,**同一 Message 信封、同一处协议定义**。 信封格式:`{"action":"...","payload":...}`(`Message` 结构体,payload 为 `json.RawMessage`)。 心跳约定:双方默认 60s 读超时 + 周期 ping(客户端 `PongTimeout` 需 ≥ 服务端 ping 周期 54s,默认值即满足)。 ## 服务端 ```go import "git.zeroonesoft.cn/golib/zogo/wsc" wsc.HandleWS(r, "/ws/chat", wsc.QuickServer(onConnect, onDisconnect), func(router *wsc.Router) { // 带响应:fn 返回 (resp, error),resp 序列化后以同名 action+".resp" 语义回包 router.On("ping", wsc.Bind(func(ctx *wsc.Context, req *PingReq) (*PingResp, error) { return &PingResp{Pong: true}, nil })) // 无响应 / 客户端约定固定回包类型时 router.On("register", wsc.BindNoResp(func(ctx *wsc.Context, req *RegisterReq) error { ... })) }) ``` - `Server`:连接池与房间管理(`GetOrCreateRoom`/`ActiveCount`…),`OnConnect/OnDisconnect/OnUpgrade` 钩子 - `Router`:action 分发,反射校验 handler 签名;`Use` 挂中间件 - `Context`:单会话上下文,实现 `context.Context`;`WriteMessage`/`WriteError`/`JoinRoom`/`Set`…,`WriteError` 使用 `WsActionError` action - gin 耦合仅在 `HandleWS`/`newContext`/`OnUpgrade` 三处入口,核心零 gin ## 客户端 ```go cli := wsc.NewClient(wsc.DefaultClientConfig("wss://cloud/ws/gateway?token=xxx")) cli.On("kick", wsc.BindPayload(func(req *KickReq) { ... })) cli.OnConnected = func() { cli.Send("register", &RegisterReq{...}) } cli.SetURL("wss://cloud/ws/gateway?token=新token") // 重连时生效 _ = cli.Connect() // AutoReconnect=true 时阻塞到连上(指数退避,稳定 10s 后重置) defer cli.Close() ``` - 自动重连:指数退避(1s→30s 封顶),连接稳定满 10s 才重置退避,防抖动时"永远 1s 一连" - 断线期间 `Send` 返回错误;重连成功重建读写泵,`OnConnected` 重新触发(在此做重注册/重订阅) ## 线程安全 `Client` 与 `Session` 的公开方法均可并发调用;发送走带缓冲通道 + 单写泵。