简体   繁体   English

node.js上的自定义TCP协议

[英]Custom TCP-Protocol on node.js

how i can implement a custom protocol on a Node.js NET-Client? 如何在Node.js NET客户端上实现自定义协议?

The problem is: 问题是:

I want to connect to a server. 我想连接到服务器。 That server has an simple protocol. 该服务器具有简单的协议。 Each packet has a length-prefix, it means the first byte say how long the packet is. 每个数据包都有一个长度前缀,这意味着第一个字节说明数据包的长度。

How i can implement that? 我该怎么实现呢? How i can read for example the first byte to get the packet-length to read the other stuff? 我如何读取例如第一个字节以获取包长度以读取其他内容?

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");
});

You'll have to maintain an internal buffer holding received data and check if it has length bytes before slicing the packet from it. 您必须维护一个内部缓冲区来保存接收到的数据,并在将数据包切片之前检查它是否具有length字节。 The buffer must be concatenated with received data until it has length bytes and emptied on receiving a full packet. 缓冲区必须与接收到的数据连接起来,直到它具有length字节为止,并在接收到完整的数据包后清空。 This can be better handled using a Transform stream. 使用Transform流可以更好地处理此问题。

This is what I used in my json-rpc implementation. 这就是我在json-rpc实现中使用的东西。 Each JSON packet is lengthPrefixed . 每个JSON数据包都是lengthPrefixed The message doesn't have to be JSON – you can replace the call to this.push(JSON.parse(json.toString())); 该消息不必是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 json-transformer

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

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