WebSocket参考
握手头部
# 客户端升级请求
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
# 服务端响应 (101 Switching Protocols)
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
JavaScript WebSocket API
const ws = new WebSocket('wss://example.com/socket');
// 连接建立
ws.addEventListener('open', (event) => {
ws.send(JSON.stringify({ type: 'subscribe', channel: 'news' }));
});
// 接收消息
ws.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
console.log('消息:', data);
});
// 错误处理
ws.addEventListener('error', (event) => {
console.error('WebSocket 错误:', event);
});
// 连接关闭
ws.addEventListener('close', (event) => {
console.log(`关闭: code=${event.code}, reason=${event.reason}`);
});
// 发送二进制数据
ws.send(new Uint8Array([1, 2, 3]).buffer);
// 主动关闭
ws.close(1000, '正常关闭');
关闭码参考
| 代码 | 名称 | 描述 |
|---|---|---|
| 1000 | 正常关闭 | 操作成功,连接完成 |
| 1001 | 离开 | 服务器关闭或客户端页面跳转 |
| 1002 | 协议错误 | 遇到协议级错误 |
| 1003 | 不支持的数据 | 收到无法接受的数据类型 |
| 1006 | 异常关闭 | 连接异常终止(无关闭帧) |
| 1007 | 无效帧 | 文本消息中含非 UTF-8 数据 |
| 1008 | 策略违规 | 消息违反服务器策略 |
| 1009 | 消息过大 | 消息体积超出处理限制 |
| 1011 | 内部错误 | 服务器遇到意外情况 |
心跳 / Ping-Pong 模式
function createWebSocket(url) {
const ws = new WebSocket(url);
let pingInterval;
ws.addEventListener('open', () => {
pingInterval = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'ping' }));
}
}, 30000); // 每 30 秒发送心跳
});
ws.addEventListener('message', (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'pong') return;
// 处理业务消息
});
ws.addEventListener('close', () => {
clearInterval(pingInterval);
setTimeout(() => createWebSocket(url), 3000); // 自动重连
});
return ws;
}
Go 服务端示例 (gorilla/websocket)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
return true // 开发环境放宽;生产环境校验 Origin
},
}
func wsHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil { return }
defer conn.Close()
for {
messageType, p, err := conn.ReadMessage()
if err != nil { break }
if err := conn.WriteMessage(messageType, p); err != nil {
break
}
}
}
readyState 值
| 值 | 常量 | 含义 |
|---|---|---|
| 0 | CONNECTING | Socket 已创建,尚未连接 |
| 1 | OPEN | 连接已打开,可以通信 |
| 2 | CLOSING | 关闭握手进行中 |
| 3 | CLOSED | 连接已关闭 |