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