I used do it like:
...
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
}
}
This has a bug: if the message's length is exactly 512 or 1024 or 2048... the loop never breaks; it will be stuck at ws.Read()
and wait without throwing io.EOF
.
Afterwards I observed that ws.Len()
is always longer than the messages's length by 4.
I rewrote the code as:
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
}
}
This way is okay.
But the number 4
is a magic code.
Is there a way to find the message's max length?
Some friends suggest separating the message packet, but I think WebSocket should not consider packet stucking or separating.
What is the most proper way for a WebSocket client to read a message?
It looks like you are using the golang.org/x/net/websocket package. It's not possible to reliably detect message boundaries using that package's Read method.
To fix, use websocket.Message to read messages.
var msg string
err := websocket.Message.Receive(ws, &msg)
if err != nil {
// handle error
}
// msg is the message
Note that the golang.org/x/net/websocket documentation says:
This package currently lacks some features found in an alternative and more actively maintained WebSocket package:
The Gorilla documentation and examples show how to read messages.