go - WebSocket 客户端如何知道消息已被完整读取?

标签 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 是一个神奇的代码。

有没有办法找到消息的最大长度?

有 friend 建议分离消息包,但我认为WebSocket不应该考虑卡包或分离。

WebSocket 客户端读取消息最合适的方式是什么?

最佳答案

看起来您正在使用 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说:

This package currently lacks some features found in an alternative and more actively maintained WebSocket package:

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

gorilla documentationexamples显示如何阅读消息。

关于go - WebSocket 客户端如何知道消息已被完整读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54997127/

相关文章:

javascript - WebSocket 连接到 'ws://localhost:3000/' 失败 : Connection closed before receiving a handshake response

sql-server - GORM GOLANG/Go msSQL UNIQUEIDENTIFIER 内部结构

go - GetById 和 CreateOrUpdate 不起作用

postgresql - 我应该如何在 Postgres 中存储 Go 的 time.Location?

ios - WS Websocket 是否能够在 Swift 中发送或接收 json 对象?

websocket - 对于低级数据通信,WebRTC 和 WebSockets 有什么区别

http - 检查来自应用程序的 Internet 连接

go - 不显示 revel flash 消息

javascript - 无法将获取的数据发送到我的 socket.io 流?

java - 为什么 Map.put() 会覆盖已经存在的键/值对中的现有值?