簡體   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