Gorilla Websocket如何将二进制数据解组为JSON?

I'm following the chat example provided by gorilla.

I still can get to unmarshal the json data sent. Should I do this in the readPump():

func (c *ChatClient) readPump() {
    defer func() {
        c.hub.unregisterChan <- c
        c.conn.Close()
    }()
    c.conn.SetReadLimit(maxMessageSize)
    c.conn.SetReadDeadline(time.Now().Add(pongWait))
    c.conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
    for {
        _, message, err := c.conn.ReadMessage()
        // =================MY CODE START=============
        var comment Comment
        err = c.conn.ReadJSON(comment)
        if err != nil {
            LogErr("readjson()", err)
            break
        }
        err = json.Unmarshal(message, comment)
        if err != nil {
            LogErr("readjson()", err)
            break
        }
        // =================MY CODE END=============

        if err != nil {
            if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
                LogErr("IsUnexpectedCloseError()", err)
            }
            break
        }
        message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))
        c.hub.broadcastChan <- message
    }
}

or in the writePump()

func (c *ChatClient) writePump() {
    ticker := time.NewTicker(pingPeriod)
    defer func() {
        ticker.Stop()
        c.conn.Close()
    }()
    for {
        select {
        case message, ok := <-c.send:
            c.conn.SetWriteDeadline(time.Now().Add(writeWait))

            // CLOSE
            if !ok {
                c.conn.WriteMessage(websocket.CloseMessage, []byte{})
                return
            }

            w, err := c.conn.NextWriter(websocket.BinaryMessage)
            if err != nil {
                LogErr("c.conn.NextWriter", err)
                return
            }
            w.Write(message)

            // Add queued chat messages to the current websocket message.
            n := len(c.send)
            for i := 0; i < n; i++ {
                w.Write(newline)
                w.Write(<-c.send)
            }

            if err := w.Close(); err != nil {
                LogErr("w.Close()", err)
                return
            }
        case <-ticker.C:
            c.conn.SetWriteDeadline(time.Now().Add(writeWait))
            if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
                LogErr("c.conn.WriteMessage()", err)
                return
            }
        }
    }
}

The LogErr() methods don't print any message. Totally lost here.

1个回答

The application reads two messages on each iteration through the loop and attempts to unmarshal both to comment. Read one message only.

The application calls ReadJSON and Unmarshal incorrectly and the error returned from these functions explains why: the application is attempting to unmarshal to a non-pointer.

The application also sends the raw bytes of the message to a channel. That looks like it might be a leftover from whatever you are copying, so I'll ignore that in the remainder of the answer.

Here's the fixed loop:

for {
    var comment Comment
    err = c.conn.ReadJSON(&comment)
    if err != nil {
        if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
            LogErr("IsUnexpectedCloseError()", err)
        }
        break
    }
    // Do something with comment
}
dongyuan8469
dongyuan8469 非常感谢! 赞赏链接,我将对其进行更多的研究。
一年多之前 回复
du9843
du9843 webSocket.send(JSON.stringify(comment))以服务器期望的格式对注释进行编码。 webSocket.send(comment)失败,因为参数不是允许的类型之一。
一年多之前 回复
duanboxue3422
duanboxue3422 为什么只有当我将JSON作为这样的字符串发送时,这才起作用:webSocket.send(JSON.stringify(comment))如果我尝试使用webSocket.send(comment),它将不起作用
一年多之前 回复
dtqf81594
dtqf81594 非常感谢!
一年多之前 回复
drsh30452
drsh30452 原始代码中对c.conn.ReadJSON和json.Unmarshal的调用返回错误,但是您没有看到记录的任何错误。 您应该确认LogErr确实按预期工作。 您还注意到该程序似乎未在服务器上输入代码。 客户端可能正在完全连接到其他端点或其他服务器。
一年多之前 回复
dongya9346
dongya9346 谢谢@ThunderCat,当我将该代码放入“ for now”连接时,它只是在客户端触发了webSocket.onclose()而不会在后端抛出任何错误。 我放了调试器,似乎没有输入那部分代码。 JS中返回的事件onClose看​​起来{{:1006,组成:false,currentTarget:WebSocket {url:“ ws:// localhost:3001 / chat”,readyState:3,eventPhase:2,isTrusted:true,srcElement:WebSocket { url:“ ws:// localhost:3001 / chat”,readyState:3,bufferedAmount:0,onopen:null,onerror:null,目标:WebSocket {url:“ ws:// localhost:3001 / chat”,readyState: 3,...}
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问