WebSocket:ghttp 支持与消息收发
WebSocket 让服务端能主动“推”消息给客户端,适合聊天、实时通知、协同编辑等场景。GoFrame v2 的 WebSocket 能力基于第三方 gorilla/websocket 实现,官方文档(“WebSocket 服务”章节与示例仓库)给出了服务器端与客户端完整示例。需要先说明一个事实:框架内曾提供 ghttp.WebSocket 封装对象,源码中已标记 Deprecated(建议直接使用第三方 websocket 库),因此本章按官方当前推荐方式编写。
基本概念
- WebSocket 连接由普通 HTTP 请求“升级”而来,因此路由注册方式与普通 handler 完全一致。
- 升级成功后,连接对象提供
ReadMessage()读取(返回消息类型与字节内容)、WriteMessage()写入。 - 消息类型常见为文本(TextMessage)与二进制(BinaryMessage)。
- ghttp 本身不做同源检查,官方文档明确要求业务层自行完成 origin 与鉴权校验。
Echo 服务端示例
以下代码来自官方文档示例的写法:路由里通过 Upgrader 用请求的 r.Response.Writer 与 r.Request 完成升级,然后进入收发循环。
package main
import (
"net/http"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gorilla/websocket"
)
func main() {
var (
s = g.Server()
wsUpGrader = websocket.Upgrader{
// 生产环境必须按业务实现真正的来源/鉴权校验
CheckOrigin: func(r *http.Request) bool { return true },
}
)
s.BindHandler("/ws", func(r *ghttp.Request) {
ws, err := wsUpGrader.Upgrade(r.Response.Writer, r.Request, nil)
if err != nil {
r.Response.Write(err.Error())
return
}
defer ws.Close()
var ctx = r.Context()
for {
msgType, msg, err := ws.ReadMessage()
if err != nil {
break // 连接关闭或出错,退出循环
}
g.Log().Infof(ctx, "received: %s", msg)
// 原样回显(Echo),消息类型通常与读取到的一致
if err = ws.WriteMessage(msgType, msg); err != nil {
break
}
}
g.Log().Info(ctx, "websocket connection closed")
})
s.SetPort(8000)
s.Run()
}
客户端与 H5 页面
Go 客户端同样来自官方示例,用 websocket.DefaultDialer.Dial 连接后收发:
ws, _, err := websocket.DefaultDialer.Dial("ws://127.0.0.1:8000/ws", nil)
if err != nil {
panic(err)
}
defer ws.Close()
if err = ws.WriteMessage(websocket.TextMessage, []byte("hello")); err != nil {
panic(err)
}
_, msg, err := ws.ReadMessage()
if err != nil {
panic(err)
}
g.Log().Infof(context.Background(), "received message: %s", msg)
浏览器端最简用法:new WebSocket("ws://127.0.0.1:8000/ws"),监听 onopen/onmessage/onclose/onerror 即可,官方文档提供了完整的 H5 聊天演示页面。
注意点
- 升级失败要处理:客户端请求并非 WebSocket 时,
Upgrade会返回错误,须写回响应并返回。 - 安全:生产环境在升级前校验来源域名、Token 等;通信内容按约定结构(如 JSON 帧)携带会话标识。
- 多连接管理(连接池、广播)需要业务自行实现,框架不内置房间/广播能力。
- 需要
wss://时,给 Server 开启 HTTPS(s.EnableHTTPS(cert, key))即可,升级逻辑不变。 - 历史遗留的
ghttp.WebSocket/r.WebSocket()用法在官方源码中已标记弃用,新代码请使用 gorilla 方案。
小结
GoFrame 的 WebSocket 开发 = 普通路由注册 + 一次协议升级 + 收发循环。把官方示例跑通后,再在“升级前鉴权”和“连接管理”两处做工程化增强,就能支撑实时业务。当前推荐的连接对象与消息 API 以官方文档 goframe.org 为准。