[英]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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.