gobwas / ws

Tiny WebSocket library for Go.
MIT License
6.1k stars 373 forks source link

an error occur when send message to chrome client with websocket upgrade by TCP #35

Closed CharXu closed 6 years ago

CharXu commented 6 years ago

I did like this as the example say: func main() { ln, err := net.Listen("tcp", "localhost:8080") if err != nil { log.Fatal(err) }

for {
    conn, err := ln.Accept()
    if err != nil {
        // handle error
    }
    _, err = ws.Upgrade(conn)
    if err != nil {
        // handle error
    }

    go func() {
        defer conn.Close()

        for {
            header, err := ws.ReadHeader(conn)
            if err != nil {
                // handle error
            }

            payload := make([]byte, header.Length)
            _, err = io.ReadFull(conn, payload)
            if err != nil {
                // handle error
            }
            if header.Masked {
                ws.Cipher(payload, header.Mask, 0)
            }

            // Reset the Masked flag, server frames must not be masked as
            // RFC6455 says.
            header.Masked = false

            if err := ws.WriteHeader(conn, header); err != nil {
                // handle error
            }
            if _, err := conn.Write(payload); err != nil {
                // handle error
            }

            if header.OpCode == ws.OpClose {
                return
            }
        }
    }()
}

}

But I found that when a js client(chrome) received server's response, an error occured: “Websocket connection to 'ws://127.0.0.1:8800' failed: Could not decode a text frame as UTF-8"

I pretty sure than server response correctly and if it was a go client everything ok.

Then I found than that's because server's response data was too long. But the Max Length that js client could decode correctly is just one key-value pair of json {"key”:"value"}. messages exceed this length will result in that error. And error message differ from the message length. Sometimes the error message is "one or more reserved bits are used"

gobwas commented 6 years ago

Hi! Do you really handle errors that occured when reading WebSocket header and other things? This problems may happen when you read "trash" bytes from the connection. Could you log the messages and its headers you receive from a client?

gobwas commented 6 years ago

Also, in your error addr is ws://127.0.0.1:8800 but example is listening 127.0.0.1:8080 =)

gobwas commented 6 years ago

@CharXu ping )

CharXu commented 6 years ago

@gobwas Pooooooooooooong! Sorry for the late reply. Addr is my mistake in writing this issue :). But in fact I do listening on :8800 and also dial :8800. As for the message receive from server, the error occured as soon as client received the msg.

`function register(ws) {

ws.onopen = function () {
    console.log("websocket on open");
    ws.send("hello, world");
};
ws.onclose = function () {
    console.log("websocket closed");
};
ws.onmessage = function (evt) {
    console.log("websocket received a message", evt.data);
};
ws.onerror = function (evt) {
    console.log("websokcet occur an error", evt);
};
}
 var ws = new WebSocket("ws://127.0.0.1:8800");
 register(ws);
 undefined
 VM408:3 websocket on open
 VM408:10 websocket received a message dfasfasdfasf
 VM408:16 WebSocket connection to 'ws://127.0.0.1:8800/' failed: One or more reserved bits are on: 
 reserved1 = 1, reserved2 = 1, reserved3 = 0
(anonymous) @ VM408:16
VM408:13 websokcet occur an error Event {isTrusted: true, type: "error", target: WebSocket, 
currentTarget: WebSocket, eventPhase: 2, …}
VM408:7 websocket closed`
gobwas commented 6 years ago

Can you please give me the full listing of your go program? With one you gave me first I cannot reproduce any issue. What go version do you use? Are there any proxies behind go server?

CharXu commented 6 years ago

@gobwas Oh, I have founded the reason. I make some mistake when use ws.NewTextFrame()

In the example, len(payload)'s length is header.Length because they both received from

cli

if err := ws.WriteHeader(conn, header); err != nil {
            // handle error
        }

if _, err := conn.Write(payload); err != nil {
            // handle error
        }

But when I want to send a new custom message of server, I do like this:

if err := ws.WriteHeader(conn, header); err != nil {
        //
}

frm := ws.NewTextFrame(str)
if err := ws.Write(conn, frm); err != nil {
    //
}

Year, it's my fault that write the header twice in ws.WriteHeader() and ws.NewTextFrame()

I am trribly sorri about that. :(

gobwas commented 6 years ago

Thats ok =)