Node JS Net事件:连接与连接

Mik*_*keC 2 node.js

何时触发net.Server的连接事件与net.Socket连接事件。他们是同一事件吗?我看过一个代码示例,其中net.createServer函数的处理程序(处理连接事件)在其中也包含以下代码

    var server = net.createServer(function (client) {
var id = client.remoteAddress + ':' + client.remotePort;
client.on('connect', function() {
channel.emit('join', id, client);
});
client.on('data', function(data) {
data = data.toString();
channel.emit('broadcast', id, data);
});
});
Run Code Online (Sandbox Code Playgroud)

这不正确吗?是否不需要此侦听器/永不命中..即,发射应该在侦听器之外。

kav*_*are 5

根据您在此处发布的代码,我假设您正在阅读《Action.Node.js》,而导致问题的是示例代码。在这种情况下,您可以参考以下类似问题:NodeJS events on('connect')error

摘要

简而言之,这2个事件被2个不同的对象接收。

connect事件由套接字对象接收,并在“成功建立套接字连接时”发出。另一方面,connection事件由服务器对象接收,并在“建立新连接时”发出。

请注意,当客户机命中节点并创建套接字时,将net.createServer(callback)自动调用for的回调,因此您不必在此客户机-服务器套接字中手动注册另一个事件处理程序,该事件处理程序client.on('connect', function() { });在您的代码中。


概念

@ 3y3所述,net在node.js中有2种使用模块的方式,分别是createConnectioncreateServer

为了更好地理解它是如何工作的,您可以使用以下图表作为示例:

在此处输入图片说明

net.createServer

当需要netmodule和时createServer,您基本上可以创建一个服务器以供客户端(通过http的浏览器,通过telnet的终端等)连接。

考虑以下代码:

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

var channel = new events.EventEmitter();

var server = net.createServer(function (socket) {
  var id = socket.remoteAddress + ': ' + client.remotePort;
  console.log('Server connected', id);
  channel.emit('join', id, socket);

  socket.on('data', function(data) {
    data = data.toString();
    channel.emit('broadcast', id, data);
  });
}).listen(8888);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,回调的参数createServer是服务器和客户端之间的“套接字”。在示例代码中,Node.js in Action的作者将其称为client,这可能会让您感到困惑,但这实际上是相同的概念:它是与客户端相关的对象,其中包含服务器执行某些操作的方法。

请注意,此回调已在服务器上注册并在建立连接的同时被调用。这是connection事件的结果,在这种情况下,当客户端命中服务器上的端口8888时,该事件会发送到服务器。放置在此回调中的所有函数将立即执行。就我们而言,我们做了三件事:

  • Console.log服务器上的客户端ID
  • 向通道对象发出“加入”事件
  • 为“数据”事件注册一个事件监听器(即,当客户端发送数据时调用)

不需要client.on('connect', function() { // do something }),由于服务器连接事件的回调是我们刚刚提到的事件。那么目的是clinet.on('connect')什么?

net.createConnection

通过使用此功能,可以创建“到服务器的连接”,而不是创建服务器本身。换句话说,就像您打开终端并使用telnet连接到服务器一样,只有这种情况发生在服务器代码库中(即,在您的节点环境中,如图Client x所示)

考虑以下代码:(再次基于@ 3y3的示例):

var Client = net.createConnection;
var client = Client({port: 8888, localAddress: '127.0.0.1', localPort: 51000});

client.on('connect', function() {
  var id = this.localAddress + ': ' + this.localPort;
  console.log('Client connected', id);
});
Run Code Online (Sandbox Code Playgroud)

在这里,我们在节点中构建一个客户端,并通过端口8888连接到服务器,端口8888是我们之前定义的。localPort并且localAddress被定义为任意,仅是本地环境中终端连接的模拟。

然后,我们在此客户端上注册事件处理程序,因此,当此客户端连接到服务器时,它将接收一个connect事件并执行此事件处理程序。如果您在带有节点的同一文件中运行两个代码段,则会看到两个

Client connected 127.0.0.1: 51000
Server connected ::ffff:127.0.0.1: 51000
Run Code Online (Sandbox Code Playgroud)

在控制台中。


结论

如果要在远程客户端连接到服务器时执行某些操作,只需将要执行的行放在的回调函数中net.createServer(function(socket) { // your lines here })

client.on('connect', function() {});在您的节点环境等人工构建的客户。

有关套接字对象和服务器对象的更多信息,请参阅此处的官方文档。

您可以根据自己的情况使用以下修订的代码:

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 (senderId !== id) {
      this.clients[id].write(message);
    }
  };

  this.on('broadcast', this.subscriptions[id]);
});

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

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

});

server.listen(8888);

var Client = net.createConnection;
var client = Client({port: 8888, localAddress: '127.0.0.1', localPort: 51000});

client.on('connect', function() {
  var id = this.localAddress + ': ' + this.localPort;
  console.log('Client connected', id);
});
Run Code Online (Sandbox Code Playgroud)