Gorilla websocket 错误:关闭 1007 Illegal UTF-8 Sequence

Posted

技术标签:

【中文标题】Gorilla websocket 错误:关闭 1007 Illegal UTF-8 Sequence【英文标题】:Gorilla websocket error: close 1007 Illegal UTF-8 Sequence 【发布时间】:2015-07-09 08:45:25 【问题描述】:

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

ReadMessage 失败: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)
            
        
    

【问题讨论】:

您是否在客户端或代理中收到错误?无论如何,websockets 要求发送的数据是正确的 utf-8。如果message 不是有效的 utf-8,则至少在客户端会失败。尝试将消息转义或转换为 utf-8,看看是否仍然会发生这种情况。 我的代理出现错误。此外,我很确定消息是有效的 utf-8。这只是一个带有随机字符串的简短测试 json 数据 [A-Z0-9] 那么我觉得可疑的是clients[clientId].WriteMessage(...)。可能有两个单独的 goroutine 同时向同一个客户端写入数据(也许我们以某种方式为两个客户端 ID 建立了一个连接?您的代码没有提供足够的上下文)。这不是线程安全的,并且会导致写入损坏的数据,从而导致此错误。 我正在使用并发映射,我只是想保持示例简单。 您可能正在使用并发映射,但是两个 goroutine 仍然可以同时写入,即使它们没有同时访问映射。 【参考方案1】:

总结我的cmets作为答案:

当您写入客户端时,您从 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 方法实现中添加互斥锁来保护您的客户端免受它的影响。

顺便说一句,实际上不是用互斥锁来保护这个方法,一个更好、更“go-ish”的方法是使用一个通道来写入消息,每个客户端都有一个 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 <- &messagemsgtype: messageType, msg: messageText


func (c *client)writeLoop() 
   go func() 
       for msg := ragne c.msgqueue 
           c.actuallyWriteMessage(msg)
       
   ()

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

【讨论】:

以上是关于Gorilla websocket 错误:关闭 1007 Illegal UTF-8 Sequence的主要内容,如果未能解决你的问题,请参考以下文章

Go websocket错误:关闭1006(异常关闭):意外EOF

go-webSocket——gorilla

go语言webSocket框架——gorilla

go mod下载依赖错误Get https://sum.golang.org

golang gorilla websocket例子

带有多余通道的大猩猩 websocket 示例? [关闭]