node.jswebsocketnodejs-server

Why is Net.socket receiving wrong data when receiving fragmanted websocket frames?


I have following code that establishes connections and listens for data from a websocket client

Server (nodejs)

const server = net.createServer((c) => {
    console.log('client connected');
    c.on('data',(data) => {
        let parsedData = parseHTML(data)
        // check if incoming data is an http request
        if(typeof parsedData != "boolean" && parsedData.type == "GET" ){
            let clientKey = parsedData.headers["Sec-WebSocket-Key"]
            // create an http response
            let response = constructWebSocketHttpResponse(clientKey)
            c.write(Buffer.from(response,"utf-8"))
        }
        else{
            // print out websocket data
            console.log(data)
        }
        })
    })

  server.listen(8124, () => {
    console.log('server bound');
  });

Client (js in browser)

let ws = new WebSocket("ws://192.168.1.79:8124");

ws.addEventListener('open', (event) => {
    console.log("sending hello")
    ws.send("hello")
});

const fileInput = <HTMLInputElement>document.getElementById("file")
const send = document.getElementById("send")

send!.addEventListener("click",() => {
    if(fileInput.files)
        ws.send(fileInput.files[0])
})

The "hello" which gets sent when the page gets loaded, is received successfully by the server, and I'm able to parse that websocket frame. However, when I send a file and it gets fragmanted ONLY the first frame is received correctly in nodejs, each consecutive data seems either like gibberish or isn't formated well.

I checked with Wireshark to see what data I was actually receiving. If let's say in wireshark i got 19 websocket packets for a given file, I also got 19 console.log outputs in my server-side code. However only the first packet, the initial hello frame and the first binary frame are received correctly others are completely different.


Solution

  • Solved, the problem was that I was getting data in TCP chunks, so I had to concatenate those chunks to get a full websocket frame. Sometimes you'd get a whole frame plus some data from the next frame so keep that in mind for anyone reading this in the future.