繁体   English   中英

node.js上的自定义TCP协议

[英]Custom TCP-Protocol on node.js

如何在Node.js NET客户端上实现自定义协议?

问题是:

我想连接到服务器。 该服务器具有简单的协议。 每个数据包都有一个长度前缀,这意味着第一个字节说明数据包的长度。

我该怎么实现呢? 我如何读取例如第一个字节以获取包长度以读取其他内容?

var net         = require('net');
var client      = new net.Socket();

client.connect(2204, 'myexampledomain.com', function() {
    console.log('Connecting...', protocol);
});

client.on('data', function(data) {

    console.log('DATA: ' + data);
});

client.on('end', function() {
    console.log('end');
});

client.on('timeout', function() {
    console.log('timeout');
});

client.on('drain', function() {
    console.log('drain');
});

client.on('error', function() {
    console.log('error');
});

client.on('close', function() {
    console.log('Connection closed');
});

client.on('connect', function() {
    console.log('Connect');
    client.write("Hello World");
});

您必须维护一个内部缓冲区来保存接收到的数据,并在将数据包切片之前检查它是否具有length字节。 缓冲区必须与接收到的数据连接起来,直到它具有length字节为止,并在接收到完整的数据包后清空。 使用Transform流可以更好地处理此问题。

这就是我在json-rpc实现中使用的东西。 每个JSON数据包都是lengthPrefixed 该消息不必是JSON –您可以替换对this.push(JSON.parse(json.toString()));的调用this.push(JSON.parse(json.toString()));

var Transform = require('stream').Transform;

function JsonTransformer(options) {
    if (!(this instanceof JsonTransformer)) {
        return new JsonTransformer(options);
    }
    Transform.call(this, {
        objectMode: true
    });
/*Transform.call(this);
    this._readableState.objectMode = false;
    this._writableState.objectMode = true;*/
    this.buffer = new Buffer(0);
    this.lengthPrefix = options.lengthPrefix || 2;
    this._readBytes = {
        1: 'readUInt8',
        2: 'readUInt16BE',
        4: 'readUInt32BE'
    }[this.lengthPrefix];
}

JsonTransformer.prototype = Object.create(Transform.prototype, {
    constructor: {
        value: JsonTransformer,
        enumerable: false,
        writable: false
    }
});


function transform() {
    var buffer = this.buffer,
        lengthPrefix = this.lengthPrefix;
    if (buffer.length > lengthPrefix) {
        this.bytes = buffer[this._readBytes](0);
        if (buffer.length >= this.bytes + lengthPrefix) {
            var json = buffer.slice(lengthPrefix, this.bytes + lengthPrefix);
            this.buffer = buffer.slice(this.bytes + lengthPrefix);
            try {
                this.push(JSON.parse(json.toString()));
            } catch(err) {
                this.emit('parse error', err);
            }

            transform.call(this);
        }
    }
}

JsonTransformer.prototype._transform = function(chunk, encoding, next) {
    this.buffer = Buffer.concat([this.buffer, chunk]);
    transform.call(this);
    next();
}

JsonTransformer.prototype._flush = function() {
    console.log('Flushed...');
}

var json = new JsonTransformer({lengthPrefix: 2});
var socket = require('net').createServer(function (socket) {
    socket.pipe(json).on('data', console.log);
});
socket.listen(3000);


module.exports = JsonTransformer;

json-transformer

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM