如何从 websocket 连接重组 TCP 块

How to reassemble TCP chunks from websocket connection

我有一个用 node.js 编写的 websocket 服务器,没有任何库。发送消息工作正常。但是当我从客户端向服务器发送一个大文件时,没有碎片化的 websocket 消息。只有一个 websocket 帧,FIN 位设置为 1。文件以 tcp 块的形式分块。 那么我如何告诉 "socket.on("data".." 侦听器,给我所有的 tcp 片段,以便我可以重新组装它们? 我如何将 websocket 框架与 tcp 块分开?

您将需要一个 websocket 解析器。我认为您不会期望这里有很多代码,所以我将 link 放入我为我的 Web 框架 simpleS.

编写的 websocket 解析器

您可以尝试将其用于某些学习目的,但我建议使用像我提到的那样的现成框架。 websocket 解析器位于:https://github.com/micnic/simpleS/blob/master/lib/parsers/ws.js

快速入门:

wsParser(limit, client)

limit - 接收帧/消息的字节数限制(零表示无穷大,我使用 0 表示从服务器接收的数据)

client - 指定解析器是在客户端还是服务器端使用的布尔值

解析器可以用作常规可写流:

var parser = new wsParser(0, false);

socket.pipe(parser);

parse.on('error', function (error) {
    // handle the error
}.on('frame', function (frame) {
    // handle the frame

    /*
      The structure of a frame:
      {
        data: buffer,
        fin: boolean,
        length: int,
        masked: boolean,
        opcode: int
      }
    */
});

更新

简化的解析过程解释:

var buffer = new Buffer(0);  // intermediate container for data
var frame = null;            // frame object
var limit = 0;               // limit in bytes for data, may be any needed value
var message = new Buffer(0); // message data container
var state = 0;               // flag for the current parser state
var index = 0;               // read index inside the buffer data

socket.on('readable', function () {
    var data = this.read() || new Buffer(0); // get the new received data

    buffer = Buffer.concat([buffer, data]);  // concat the received data

    if (state === 0) { // waiting for a new frame
        frame = {      // create the frame object
            data: new Buffer(0),
            fin: (buffer[index] & 128) === 128,
            length: buffer[index + 1] & 127,
            masked: (buffer[index + 1] & 128) === 128,
            opcode: buffer[index] & 15
        };

        // validate the frame based on the websocket protocol limitations

        // set the next step flag based on the frame properties
        if (frame.length > 125) {
            state = 1;
        } else {
            state = 2;
        }

        index += 2; // skip frame header bytes
    }

    if (state === 1) { // get extended payload length
        if (frame.length === 126) {
            // get the next 16 bits for the extended payload length

            index += 2; // skip extended payload length
        } else if (frame.length === 127) {
            // get the next 32 bits for the extended payload length

            index += 8; // skip extended payload length
        }

        state = 2;
    }

    if (state === 2) { // get the masking key
        frame.mask = buffer.slice(index, index + 4);

        index += 4; // skip masking key bytes

        state = 3;
    }

    if (state === 3) { // get payload data
        frame.data = buffer.slice(index, /* some offset */);

        // unmask frame data
        // prepare the message
        // reset parser state and frame object
    }
});