Nodejs net.createServer() 使用方法

Nodejs net.createServer() 使用方法

代码:

var events = require('events');
var net = require('net');

var channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};

channel.on('join', function(id, client){
  this.clients[id] = client;
  this.subscriptions[id] = function(senderId, message){
    if(id != senderId){
      this.clients[id].write(message);
    }
  };
  this.on('broadcast', this.subscriptions[id]);
});

var server = net.createServer(function(client){   //here
  var id = client.remoteAddress + ":" + client.remotePort;
  client.on('connect', function(){	//事件1 <<问题行
    channel.emit('join', id, client); 
  });
  client.on('data', function(data){	//事件2
    data = data.toString();
    channel.emit('broadcast', id, data);
  });
});

server.listen(8888);

最近在看Node.js in action一书,里面有个例子是建一个简单的聊天服务器

但是我运行代码后发现有问题,不知道怎么解决,看文档也找不到详细解释,所以到这里请教。 createServer的回调函数里面给新建的链接添加了个connect事件(见上面的问题行),但是我尝试用telnet连接的时候发现connect事件无法被触发,而data事件却可以触发,表明已经连接成功了,这让我很郁闷,所以想请教下这个connect事件的一些细节。

万分感谢。


4 回复

当然,我可以帮助你解答关于 net.createServer() 的使用方法以及如何处理你提到的问题。

首先,我们来理解一下 net.createServer() 的基本用法。net.createServer() 是 Node.js 中用于创建 TCP 服务器的一个核心 API。它接受一个可选的回调函数,该回调函数会在每个新客户端连接时被调用。

示例代码

让我们先来看一个简化版本的示例代码:

var net = require('net');

var server = net.createServer(function(client) {
  console.log('Client connected:', client.remoteAddress, client.remotePort);

  client.on('end', function() {
    console.log('Client disconnected');
  });

  client.on('data', function(data) {
    console.log('Received data:', data.toString());
    client.write('Echo: ' + data);
  });
});

server.listen(8888, function() {
  console.log('Server is listening on port 8888');
});

在这个示例中,我们创建了一个简单的 TCP 服务器,每当有新的客户端连接时,会打印一条消息,并且在接收到数据时会回显数据。

解决你的问题

关于你提到的 connect 事件不能触发的问题,实际上 net.Socket 对象没有 connect 事件。connect 事件通常用于 net.connect() 创建的客户端对象。对于服务器端来说,客户端连接的建立是自动完成的,因此不需要监听 connect 事件。

如果你想要在客户端连接时执行某些操作,可以在 net.createServer() 的回调函数中进行处理,如上所示的 console.log('Client connected:', client.remoteAddress, client.remotePort);

你的原始代码中的问题

在你的原始代码中,client.on('connect', ...) 这一行实际上是不必要的。因为每当一个新的客户端连接到服务器时,net.createServer() 的回调函数会被立即调用。你应该在回调函数内部处理客户端连接后的逻辑,而不是试图监听 connect 事件。

你可以将你的代码修改为如下所示:

var events = require('events');
var net = require('net');

var channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};

channel.on('join', function(id, client){
  this.clients[id] = client;
  this.subscriptions[id] = function(senderId, message){
    if(id != senderId){
      this.clients[id].write(message);
    }
  };
  this.on('broadcast', this.subscriptions[id]);
});

var server = net.createServer(function(client){   
  var id = client.remoteAddress + ":" + client.remotePort;
  channel.emit('join', id, client); 

  client.on('data', function(data){    
    data = data.toString();
    channel.emit('broadcast', id, data);
  });
});

server.listen(8888);

这样,每次有新的客户端连接时,channel.emit('join', id, client); 会被调用,从而注册相应的事件处理器。


服务器只会触发 connection 事件,亦即是调用 createServer 中的回调函数。 connect 是客户端调用 connect() 函数成功连接后才会触发的 你再看看文档中的上述两个事件和两个函数

据我所知 你说的这个net.Socket对象的connect事件应该是你开发tcp的客户端时,连接到服务器时(通过socket.connect()方法),才会触发你说的connect事件。 你是在开发服务器,不是客户端。

在Node.js中使用net.createServer()来创建一个TCP服务器时,内置了一些常见的事件,如'connection''close''error'等。对于客户端连接的处理,应该关注的是'connection'事件,而不是'connect'事件。'connect'事件实际上是客户端用来监听服务器响应的事件,并不会在服务器端触发。

以下是修正后的代码示例:

var events = require('events');
var net = require('net');

var channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};

channel.on('join', function (id, client) {
  this.clients[id] = client;
  this.subscriptions[id] = function (senderId, message) {
    if (id != senderId) {
      this.clients[id].write(message);
    }
  };
  this.on('broadcast', this.subscriptions[id]);
});

var server = net.createServer(function (client) { // 这里
  var id = client.remoteAddress + ":" + client.remotePort;
  
  client.on('connect', function () { // 这里不需要
    console.log("Client connected");
  });

  client.on('data', function (data) { // 事件2
    data = data.toString();
    channel.emit('broadcast', id, data);
  });

  client.on('end', function () {
    delete channel.clients[id];
    delete channel.subscriptions[id];
  });
});

server.listen(8888, function () {
  console.log('Server listening on port 8888');
});

解释:

  1. 事件:服务器端关注的事件是'connection',但在这个例子中,我们直接在net.createServer的回调函数中处理客户端连接,因此不需要显式地处理'connect'事件。

  2. 连接处理:在net.createServer的回调函数中,我们通过监听'data'事件来接收来自客户端的数据,并通过'broadcast'事件广播给所有连接的客户端。

  3. 断开连接:我们还添加了一个'end'事件处理程序,当客户端断开连接时,从订阅列表中移除该客户端。

  4. 错误处理:建议添加对'error'事件的处理,以确保服务器能够优雅地处理异常情况。

通过这种方式,你可以创建一个简单的聊天服务器,其中每个连接的客户端都能接收到其他客户端发送的消息。

回到顶部