为了账号安全,请及时绑定邮箱和手机立即绑定

Gorilla websocket 错误:关闭 1007 非法 UTF-8 序列

Gorilla websocket 错误:关闭 1007 非法 UTF-8 序列

Go
芜湖不芜 2021-10-18 17:23:23
我正在尝试为 GlassFish 实现一个 websocket 代理服务器。如果我尝试连接多个客户端,则会出现错误:ReadMessage 失败:websocket:关闭 1007 非法 UTF-8 序列。我确信 GlassFish 服务器发送了正确的数据,因为同一台服务器与另一个使用 node.js 实现的代理服务器一起正常工作。func GlassFishHandler(conn *websocket.Conn){    defer conn.Close()    conn.SetReadDeadline(time.Now().Add(1000 * time.Second))    conn.SetWriteDeadline(time.Now().Add(1000 * time.Second))    fmt.Println("WS-GOLANG PROXY SERVER: Connected to GlassFish")    for {        messageType, reader, err := conn.NextReader()        if err != nil {            fmt.Println("ReadMessage Failed: ", err) // <- error here        } else {            message, err := ioutil.ReadAll(reader)            if (err == nil && messageType == websocket.TextMessage){                var dat map[string]interface{}                if err := json.Unmarshal(message, &dat); err != nil {                    panic(err)                }                 // get client destination id                clientId := dat["target"].(string)                fmt.Println("Msg from GlassFish for Client: ", dat);                // pass through                clients[clientId].WriteMessage(websocket.TextMessage, message)            }        }    }}
查看完整描述

1 回答

?
慕虎7371278

TA贡献1802条经验 获得超4个赞

总结我的评论作为答案:


当您写入客户端时,您从 GlassFish 消息中获取 clientId,从地图中获取客户端,然后写入它 - 基本上是clients[clientId].WriteMessage(...)。


虽然您的地图访问可以是线程安全的,但写入不是,因为这可以被视为:


// map access - can be safe if you're using a concurrent map

client := clients[clientId]


// writing to a client, not protected at all

client.WriteMessage(...)

所以可能发生的事情是两个单独的 goroutine 同时写入同一个客户端。您应该通过在WriteMessage方法实现中添加互斥锁来保护您的客户端免受它的影响。


顺便说一句,实际上不是使用互斥锁来保护此方法,而是使用一个通道来编写消息,并且每个客户端使用一个 goroutine 从通道中消费并写入实际套接字,而不是使用互斥锁来保护此方法。


所以在客户端结构中我会做这样的事情:


type message struct {

   msgtype string

   msg string

 }


type client struct {

    ...

    msgqueue chan *message

}



func (c *client)WriteMessage(messageType, messageText string) {

   // I'm simplifying here, but you get the idea

   c.msgqueue <- &message{msgtype: messageType, msg: messageText}

}


func (c *client)writeLoop() {

   go func() {

       for msg := ragne c.msgqueue {

           c.actuallyWriteMessage(msg)

       }

   }()

}

并且在创建新的客户端实例时,只需启动写入循环


查看完整回答
反对 回复 2021-10-18
  • 1 回答
  • 0 关注
  • 388 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信