如何从websocket连接重新组装TCP块

时间:2015-04-27 12:43:12

标签: javascript node.js sockets tcp websocket

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

1 个答案:

答案 0 :(得分:0)

您需要一个websocket解析器。我不认为你会在这里期待很多代码,所以我将链接到我为我的Web框架simpleS编写的websocket解析器。

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

快速入门:

wsParser(limit, client)

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

client - boolean指定是在客户端还是服务器端使用解析器

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

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
    }
});