我正在尝试使用nodejs 实现类似代理的应用程序。当客户端连接时,它将连接到 2 个服务器 A 和 B。如果客户端发送“A”,它将发送到服务器 A,否则发送到服务器 B。并且来自服务器 A 和 B 的所有响应都将通过管道返回给客户端。我用过这个网站上的衬垫模块 https://strongloop.com/strongblog/practical-examples-of-the-new-node-js-streams-api/ 将传入消息拆分为行。
如果只有一个客户端连接到服务器,我的代码就可以工作。但是,如果有多个客户端连接。其他客户端消息始终发送到为第一个客户端建立的服务器套接字。线性可读事件似乎总是引用创建的第一个服务器套接字,但我认为它应该是局部变量。
任何人都知道我的代码有什么问题。
非常感谢。
var net = require('net');
var fs = require('fs');
var util = require('util');
var liner = require('./liner');
var server = net.createServer(function (clientSocket) {
console.log('client connected');
var serverSocket2 = null;
var serverSocket = net.connect({ host: '127.0.0.1', port: 9001 },
function () {
console.log('connected to server:' + serverSocket.remoteAddress);
serverSocket2 = net.connect({ host: '127.0.0.1', port: 9002 },
function () {
console.log('connected to server ' + serverSocket2.remoteAddress);
// pipe the client input to 2 server
clientSocket.pipe(liner);
// pipe server output to client socket
serverSocket.pipe(clientSocket);
serverSocket2.pipe(clientSocket);
});
});
liner.on('readable', function () {
var line;
while (null !== (line = liner.read())) {
if (line == "A") {
serverSocket2.write(line + "\r\n");
}
if (line == "B") {
serverSocket.write(line + "\r\n");
}
}
});
clientSocket.on('end', function () {
console.log('client disconnected');
serverSocket.end();
serverSocket2.end();
});
});
server.listen(8123, function () { //'listening' listener
console.log('server bound');
});
解决方案很简单:不要为所有连接共享全局
liner
实例。相反,请将您链接的文章中的 liner
示例转换为继承自 stream.Transform
的构造函数,并使用它进行实例化。例如(使用链接文章中的代码):
var inherits = require('util').inherits;
var stream = require('stream');
function Liner() {
if (!(this instanceof Liner))
return new Liner();
stream.Transform.call(this, { objectMode: true });
}
inherits(Liner, stream.Transform);
Liner.prototype._transform = function(chunk, encoding, done) {
var data = chunk.toString();
if (this._lastLineData)
data = this._lastLineData + data;
var lines = data.split('\n');
this._lastLineData = lines.splice(lines.length-1,1)[0];
lines.forEach(this.push.bind(this));
done();
};
Liner.prototype._flush = function (done) {
if (this._lastLineData)
this.push(this._lastLineData);
this._lastLineData = null;
done();
};
module.exports = Liner;
然后像这样使用它:
var Liner = require('./liner');
var server = net.createServer(function(clientSocket) {
var liner = new Liner();
// ...
});
readline
模块可以实现同样的效果。例如:
var readline = require('readline');
var net = require('net');
var server = net.createServer(function(clientSocket) {
console.log('client connected');
var rl;
var serverSocket2 = null;
var serverSocket = net.connect({ host: '127.0.0.1', port: 9001 },
function () {
console.log('connected to server:' + serverSocket.remoteAddress);
serverSocket2 = net.connect({ host: '127.0.0.1', port: 9002 },
function () {
console.log('connected to server ' + serverSocket2.remoteAddress);
// pipe the client input to 2 server
rl = readline.createInterface({
input: clientSocket
});
rl.on('line', lineHandler);
// pipe server output to client socket
serverSocket.pipe(clientSocket);
serverSocket2.pipe(clientSocket);
}
);
}
);
function lineHandler(line) {
if (line === "A") {
serverSocket2.write(line + "\r\n");
} else if (line === "B") {
serverSocket.write(line + "\r\n");
}
}
clientSocket.on('end', function() {
console.log('client disconnected');
serverSocket.end();
serverSocket2.end();
});
});
server.listen(8123, function() {
console.log('server bound');
});