防止减少套接字消息

时间:2018-05-07 17:15:14

标签: javascript node.js sockets

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个字符,或者该计算是否错误?

1 个答案:

答案 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个字节可以拆分的可能性。