LOADING
1406 words
7 minutes
Game_webSocket

一、一张图看懂 HTTP、SSE、WebSocket 的区别

HTTP:你问一次,我答一次

客户端 ────请求────> 服务端
客户端 <────响应──── 服务端
[连接关闭]

SSE:我只听,不说话

客户端 ────请求────> 服务端
客户端 <────数据1──── 服务端
客户端 <────数据2──── 服务端
客户端 <────数据3──── 服务端
[连接保持,但客户端不能发消息]

WebSocket:随时聊,聊多久都行

客户端 ────握手────> 服务端
客户端 <───握手成功─── 服务端
[连接保持]
客户端 ────消息A───> 服务端
客户端 <───消息B──── 服务端
客户端 ────消息C───> 服务端
客户端 <───消息D──── 服务端

对比表

HTTPSSEWebSocket
谁可以主动说话只有客户端只有服务端双方都可以
连接像什么打电话,说完就挂听收音机,只能接收拉微信群,随时聊
小程序能用吗
做什么用普通接口服务端推送聊天、AI对话

二、核心概念:连上只是第一步

WebSocket 的连接不是一个简单的开关,它有 4 个阶段:

[未连接] ──调用connect──> [连接中] ──TCP通了──> [已连接] ──认证成功──> [可用]
↑ │
└──────────────────── 断线自动重连 ──────────────────────┘

关键点已连接 只代表网线插上了,可用 才代表业务能用(比如用户登录验证通过)。


三、最简示例:5 行核心代码

// 小程序端
const socket = wx.connectSocket({ url: 'wss://your-server.com' })
socket.onOpen(() => socket.send({ data: 'Hello' }))
socket.onMessage(res => console.log('收到:', res.data))

这就是 WebSocket 的本质。其他所有东西(心跳、重连、认证)都是为了让它在真实网络环境里稳定运行。


四、工程化四大问题及解法

问题1:怎么知道连接还活着?

场景:用户把手机放兜里,App 在后台,连接可能已经被系统切断了。

解法:心跳

[客户端] 每30秒 ──ping──> [服务端]
[服务端] <──pong── [客户端]
如果10秒没收到pong → 认为连接断了 → 触发重连

问题2:断线了怎么办?

场景:用户进电梯,信号断了。

解法:指数退避重连

第1次断线 → 等1秒重连
第2次断线 → 等2秒重连
第3次断线 → 等4秒重连
...
最多等30秒

为什么要这样?如果 1000 个用户同时断线,同时重连,服务器会被打爆。

问题3:重连后消息丢了怎么办?

场景:断线期间服务端发了 3 条消息,客户端没收到。

解法:记住”读到哪里了”

客户端记录:session_123 我已经收到第5个分片了
重连时告诉服务端:我收到第5个了
服务端:那就从第6个开始发

问题4:怎么让业务代码不关心连接细节?

解法:发布-订阅模式

// 连接层只管连接和分发
ws.onMessage(msg => emit(msg.type, msg.data))
// 业务层只管订阅
ws.on('stream_chunk', data => 拼接内容)
ws.on('game_status', data => 更新进度)

这样,新增一个消息类型只需要加一行 ws.on(...),不用改连接层的代码。


五、完整的连接管理架构

┌─────────────────────────────────────────────────────────┐
│ 业务层 │
│ on('stream_chunk') on('game_status') on('reply') │
└─────────────────────────────────────────────────────────┘
│ emit(event_type, data)
┌─────────────────────────────────────────────────────────┐
│ 事件分发层 │
│ 根据 event_type 调用对应的业务回调 │
└─────────────────────────────────────────────────────────┘
│ 解析消息
┌─────────────────────────────────────────────────────────┐
│ 连接管理层 │
│ ├── 连接/重连 │
│ ├── 心跳保活 │
│ ├── 认证 │
│ └── 网络状态监听 │
└─────────────────────────────────────────────────────────┘
│ 收发数据
┌─────────────────────────────────────────────────────────┐
│ 微信 WebSocket API │
└─────────────────────────────────────────────────────────┘

六、实际业务流程:AI 对话

1. 用户输入"你好"
2. 界面立即显示用户消息(pending 状态,灰色)
3. WebSocket 发送 { type: 'chat', content: '你好' }
4. 服务端返回 stream_chunk(一个字一个字地推)
┌─────────────────────────────────────────┐
│ chunk1: '你' │
│ chunk2: '好' │
│ chunk3: '呀' │
│ chunk4: '!' │
└─────────────────────────────────────────┘
5. 客户端边收边拼,界面上一个字一个字冒出来
6. 收到 stream_done,结束

流程图

用户 ──发送消息──> 小程序 ──WebSocket──> 服务端
│ stream_chunk(你)
界面更新("你")
│ stream_chunk(好)
界面更新("你好")
│ stream_done
标记完成

七、什么时候用,什么时候不用

✅ 用 WebSocket

场景为什么
AI 对话需要服务端主动推流式内容
游戏状态推送需要实时更新进度
协作编辑需要双向同步

❌ 不用 WebSocket

场景用什么
获取用户信息HTTP GET
提交表单HTTP POST
列表分页HTTP + 缓存

判断标准

需要服务端主动推送消息?
├── 是 → 需要长连接
│ ├── 我也要发消息 → WebSocket
│ └── 我只收不发 → SSE(小程序不支持,还是WebSocket)
└── 否 → HTTP 就够了

八、代码结构(最小可用版)

websocket-manager.js
class WsManager {
constructor(url) {
this.url = url
this.handlers = new Map() // 事件名 → 回调函数数组
}
connect() {
this.socket = wx.connectSocket({ url: this.url })
this.socket.onMessage((res) => {
const { event_type, data } = JSON.parse(res.data)
this.emit(event_type, data) // 分发给订阅者
})
this.socket.onOpen(() => this.send({ event_type: 'auth', token: getToken() }))
}
on(event, callback) {
if (!this.handlers.has(event)) this.handlers.set(event, [])
this.handlers.get(event).push(callback)
}
emit(event, data) {
(this.handlers.get(event) || []).forEach(fn => fn(data))
}
send(data) {
this.socket.send({ data: JSON.stringify(data) })
}
}
// 使用
const ws = new WsManager('wss://your-server.com')
ws.connect()
ws.on('stream_chunk', (data) => {
this.setData({ content: this.data.content + data.content })
})
ws.on('stream_done', () => {
console.log('对话完成')
})

总结(4 句话)

  1. HTTP 是问一句答一句,WebSocket 是拉群聊,随时都能说话
  2. 连接有 4 个状态,只有”可用”才算真正能用
  3. 生产环境必须加:心跳、重连、状态恢复
  4. 业务层用发布-订阅,连接层和业务层解耦
Game_webSocket
/posts/2026-6-7/game_websocket/
Author
Atopos
Published at
2026-06-07
License
CC BY-NC-SA 4.0

Some information may be outdated