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.Writerr.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 为准。

笔记加载中…