gorilla websocket 错误 : close 1007 Illegal UTF-8 Sequence

标签 go websocket glassfish gorilla

我正在尝试为 GlassFish 实现一个 websocket 代理服务器。如果我尝试连接多个客户端,则会出现错误:

ReadMessage Failed: websocket: close 1007 Illegal UTF-8 Sequence.

我确信 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)
            }
        }
    }
}

最佳答案

总结我的评论作为答案:

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

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

// 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 方法实现中添加互斥体来保护您的客户端免受其影响。

顺便说一句,实际上,一种更好、更“go-ish”的方法不是使用互斥锁来保护此方法,而是使用 channel 来写入消息,并为每个客户端使用一个 goroutine,从 channel 中消费并写入实际的消息。套接字。

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

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)
       }
   }()
}

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

关于 gorilla websocket 错误 : close 1007 Illegal UTF-8 Sequence,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31312458/

相关文章:

json - 处理 HTTP 请求正文中的可选 JSON 字段

javascript - Websocket 与 SockJS 对象

webpack - Angular CLI 代理 : Redirect unsecured local websocket to secured remote websocket

Nginx 反向代理 Websocket 身份验证 - HTTP 403

java - 如何停止 EJBException 的堆栈跟踪(在每个抛出的异常中)

java - 在 netbeans 上运行项目时选择 "Remember permanently"后尝试更改服务器

macos - 如何检测什么条形码扫描仪(模拟为USB键盘输入)数据来自

go - 如何在 go 以外的文件中查找函数使用情况?

go - 预先声明的类型可以在 Go 中实现接口(interface)吗?

jakarta-ee - 用于 Java EE 的免费商业用途应用程序服务器?