function parseMessage (buff){
let obs = [];
let done = false;
let offset = 0;
let size_bytes = 4;
while(!done){
let message_size = buff.readUIntBE(offset, size_bytes);
let message = buff.slice(size_bytes + offset, size_bytes + offset + message_size).toString('utf8');
offset = size_bytes+offset+message_size;
try {
let o = JSON.parse(message.toString());
if (o && typeof o === "object") {
obs.push(o);
}
}
catch (e) {winston.error(e);winston.error(message);}
if(offset >= buff.length - 1){
done = true;
}
}
return obs;
};
client_socket.on('data', function (data) {console.log(parseMessage(data));});
我正在使用套接字将字符串化的JSON从客户端传递到服务器。字符串化的JSON前面加上4个字节来描述消息的大小。我遇到了一个错误,在几条消息之后,JSON无法解析,因为消息字符串被缩减(我认为它是在下一个'data'事件中发送的)。我的问题是,因为它超过了tcp套接字,所以消息可以被缩减,因为它可以被扩展(为什么我必须在它的大小之前添加消息)。如果是这样,有没有人有任何优雅的解决方案来解决这个问题?
客户端是用perl编写的。如果需要,我可以提供代码,但我认为这部分是正确的。
附带问题:由于前置消息大小为4个字节。这是否意味着我的消息最多可以包含(2 ^(4'bytes'* 8'bits / byte'))/ 8'bits / char'= 536,870,912个字符,或者该计算是否错误?
答案 0 :(得分:0)
这是我最终提出的解决方案
function tryParseJSON(message,fail_cb){
try {
let o = JSON.parse(message.toString());
if (o && typeof o === "object") {
return(o);
}
}
catch (err) {
fail_cb(err);
}
}
function parseMessage (active_message_buffer_size,active_message_buffer,buff){
let obs = [];
let done = false;
let offset = 0;
let size_bytes = 4;
while(!done){
if(!active_message_buffer.length){
active_message_buffer_size = buff.readUIntBE(offset, size_bytes);
}
active_message_buffer = Buffer.concat([active_message_buffer,buff.slice(size_bytes + offset, size_bytes + offset + active_message_buffer_size)])
if(active_message_buffer.length && (active_message_buffer.length === active_message_buffer_size)){
let message = active_message_buffer.toString('utf8');
let parsed_json = tryParseJSON(message,function(err){
winston.error(err);
});
if(parsed_json){
obs.push(parsed_json);
}
active_message_buffer = new Buffer(0);
}
offset = size_bytes+offset+active_message_buffer_size-1;
if(offset >= (buff.length - 1)){
done = true;
}
}
return obs;
};
net.createServer(
function(client_socket){
let active_message_buffer = new Buffer(0);
let active_message_buffer_size = null;
client_socket.on('data',function(data){console.log(parseMessage(active_message_buffer_size,active_message_buffer,data)});
}
);
它并不完美,因为它没有考虑到前4个字节可以拆分的可能性。