我正在尝试使用nodejs实现一个类似代理的应用程序。当客户端连接时,它将连接到2台服务器a和B。如果客户端发送"a",它将发送到服务器a,否则将发送到Server B。来自服务器a和服务器B的所有响应都将通过管道返回到客户端。我在这个网站上使用了liner模块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 + "rn");
}
if (line == "B") {
serverSocket.write(line + "rn");
}
}
});
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 + "rn");
} else if (line === "B") {
serverSocket.write(line + "rn");
}
}
clientSocket.on('end', function() {
console.log('client disconnected');
serverSocket.end();
serverSocket2.end();
});
});
server.listen(8123, function() {
console.log('server bound');
});