Node js,变量范围。事件处理程序始终引用创建的第一个套接字

问题描述 投票:0回答:1

我正在尝试使用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');
});
node.js stream pipe
1个回答
1
投票

解决方案很简单:不要为所有连接共享全局

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');
});
© www.soinside.com 2019 - 2024. All rights reserved.