WebSocket客户端如何知道一条消息已被完全读取?

时间:2019-03-05 07:03:33

标签: go websocket

我曾经这样做过:

    ...
    ws, err := websocket.Dial(url, "", origin)
    ...
    var buffer = make([]byte, 512)
    var rs = make([]byte, 0, 512)
L:
    for {
        m, err := ws.Read(buffer)
        if err != nil {
            if err == io.EOF {
                break L
            }
            fmt.Println(err.Error())
            return
        }
        rs = append(rs, buffer[:m]...)
        if m < 512 {
            break L
        }
    }

这有一个错误:如果消息的长度恰好是512或1024或2048 ...循环永远不会中断;它将停留在ws.Read()并等待而不会抛出io.EOF

之后,我发现ws.Len()总是比消息的长度长4。

我将代码重写为:

    var buffer = make([]byte, 512)
    var rs = make([]byte, 0, 512)
    var sum = 0
L:
    for {
        m, err := ws.Read(buffer)
        if err != nil {
            if err == io.EOF {
                break L
            }
            fmt.Println(err.Error())
            return
        }
        rs = append(rs, buffer[:m]...)
        sum+=m
        if sum >= ws.Len()-4 {
            break L
        }
    }

这种方式还可以。

但是数字4是一个神奇的密码。

是否可以找到邮件的最大长度?

一些朋友建议分离消息包,但我认为WebSocket不应该考虑消息卡住或分离。

WebSocket客户端读取消息的最正确方法是什么?

1 个答案:

答案 0 :(得分:1)

您似乎正在使用golang.org/x/net/websocket软件包。使用该程序包的Read方法无法可靠地检测消息边界。

要解决此问题,请使用websocket.Message阅读消息。

var msg string
err := websocket.Message.Receive(ws, &msg)
if err != nil {
  // handle error
}
// msg is the message

请注意,golang.org/x/net/websocket documentation表示:

  

此程序包当前缺少在替代性的且维护程度更高的WebSocket程序包中发现的一些功能:

     

https://godoc.org/github.com/gorilla/websocket

大猩猩documentationexamples展示了如何阅读消息。