标签导航:

golang websocket连接:为何一个标签页能收发消息,另一个却不行?

Golang WebSocket连接问题:单标签页正常通信,多标签页失效

本文分析并解决一个使用gorilla/websocket库开发Golang WebSocket服务器时遇到的问题:Chrome浏览器中,一个标签页可以正常收发WebSocket消息,而其他标签页则无法收发,除非刷新页面,但刷新后第一个标签页又会失效。 问题发生在Go 1.16、gorilla/websocket 1.4.2版本,Windows 10环境下。

问题根源:全局变量导致连接覆盖

用户提供的代码片段显示,WebSocket连接使用全局变量ws存储:

//部分serve代码
var ws *websocket.Conn

func Ws(c *gin.Context) {
    var err error
    ws, err = upgrader.Upgrade(c.Writer, c.Request, nil)
    // ...
}

每次有新的连接请求时,ws都会被新的连接覆盖,导致之前的连接被中断,无法收发消息。

解决方案:避免全局变量,为每个连接创建独立实例

问题在于WebSocket连接管理不当。 正确的做法是为每个客户端连接创建独立的websocket.Conn对象,避免使用全局变量。 每个连接应该在Ws函数内部独立处理,并在连接关闭后释放资源。 修改后的Ws函数应该类似这样:

func Ws(c *gin.Context) {
    conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
    if err != nil {
        // 处理错误
        return
    }
    defer conn.Close() // 确保连接关闭

    // 在这里处理每个连接的读写操作,使用 conn 而不是全局变量 ws
    go func() {
        for {
            // ... 读写消息操作,使用 conn
        }
    }()
}

通过为每个连接创建独立的连接实例,避免了连接覆盖,从而解决了多标签页通信失效的问题。 每个客户端连接拥有独立的连接对象,互不干扰,确保了所有连接都能正常工作。 关键在于理解并正确管理WebSocket连接的生命周期。