Node.js net模块~粘包处理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/themagickeyjianan/article/details/86501453

1)基本思想

很简单,消息体由2部分组成:消息头长度 + 消息体

这样在收到一个数据包时,先判断是否构成一个完整包,不够则将这次得数据缓存起来,下次接到数据则和这次的数据拼接。 够,则解析

2)粘包处理代码

初始化: 
session.last_pkg = null;

粘包处理代码:
session.on("data", function (data) {
        var last_pkg = session.last_pkg;

        if(last_pkg){
            var buf = Buffer.concat([last_pkg, data], last_pkg.length + data.length);
            last_pkg = buf;
        }else {
            last_pkg = data;
        }

        var offset = 0;
        var pkg_len = tcppkg.read_pkg_size(last_pkg, offset);
        if(pkg_len < 0){
            console.error("client 不是完整包!!!");
            session.last_pkg = last_pkg;  // 这行是我自己加的,感觉不加有问题
            return;
        }

        // offset + pkg_len <= last_pkg.length 这个成立,则至少是读取到了一个完整包
        while (offset + pkg_len <= last_pkg.length){
            var cmd_buf = Buffer.allocUnsafe(pkg_len - 2);
            last_pkg.copy(cmd_buf, 0, offset + 2, offset + pkg_len);

            // 网关收到业务进程信息
            on_recv_cmd_server_return(session, cmd_buf);

            offset += pkg_len;

            // 包处理完
            if(offset >= last_pkg.length){
                break;
            }

            pkg_len = tcppkg.read_pkg_size(last_pkg, offset);

            //
            if(pkg_len < 0){
                break;
            }
        }


        if(offset >= last_pkg.length){
            last_pkg = null;
        }else {
            var buf = Buffer.allocUnsafe(last_pkg.length - offset);
            last_pkg.copy(buf, 0, offset, last_pkg.length);
            last_pkg = buf;
        }

        session.last_pkg = last_pkg;
    });

3)打包+读取包长度的代码

var tcppkg = {

    /**
     * 返回值len 包含包头 + 包体 2部分 长度之和
     * @param pkg_data
     * @param offset
     * @returns {*}
     */
    read_pkg_size: function (pkg_data, offset) {
        if(offset > pkg_data.length - 2){
            return -1;
        }

        var len = pkg_data.readUInt16LE(offset);
        return len;
    },

    package_data: function (data) {


        // 代替data.length即可,否则不支持汉字
        var data_len = Buffer.from(data).length;

        //
        var buf = Buffer.allocUnsafe(2 + data_len);

        // 可见写入的这个长度包含: 包头 + 包体
        buf.writeInt16LE(2 + data_len, 0);

        buf.fill(data, 2);
        return buf;
    }
}

module.exports = tcppkg;

猜你喜欢

转载自blog.csdn.net/themagickeyjianan/article/details/86501453
今日推荐