Skip to content

net.Server #263

Open
Open
@yaofly2012

Description

@yaofly2012

net.Server

net.Server构造函数用于创建TCP,IPC服务。是http.Server等的基类。

基础

事件

1. connection事件:

当新建立连接(比如TCP握手完成后)时触发,创建新的net.Socket对象。

2. listening

服务已经绑定好了,正在监听连接请求。除了显示的绑定listening事件外,调用listen方法传入的callback也是会被绑定为listening处理函数(一次性绑定)。

3. ...

属性

1. listening

表示当前服务是否正在监听连接,

ObjectDefineProperty(Server.prototype, 'listening', {
  __proto__: null,
  get: function() {
    return !!this._handle; // 服务器句柄的计算值
  },
  configurable: true,
  enumerable: true
});

2. this._handle

服务器句柄,用于监听连接

listen方法

listen方法可谓是net.Server最核心的方法。调用该方法让服务监听连接请求(看着很简短但是逻辑却不简单)。

listen做了哪些事情?

以建立TCP服务(不考虑cluster)为例看看listen做了哪些事情。

  1. 创建服务器句柄(serverHandle), 即对this._handle属性赋值;
    this._handle对象是为了让nodejs调用底层libuv库创建的socket而进行的封装,即是net.Server实例和底层socket联系的桥梁。
    setupListenHandle代码片段
function setupListenHandle(address, port, addressType, backlog, fd, flags) {
  ...
if (rval === null)
      rval = createServerHandle(address, port, addressType, fd, flags);

    if (typeof rval === 'number') {
      const error = uvExceptionWithHostPort(rval, 'listen', address, port);
      process.nextTick(emitErrorNT, this, error);
      return;
    }
    this._handle = rval;

...

  // 额外赋值,这样底层收到连接请求时可以调用onconnection回调
  this[async_id_symbol] = getNewAsyncId(this._handle);
  this._handle.onconnection = onconnection;
  this._handle[owner_symbol] = this;

  // 调用底层的listen开始监听端口
  const err = this._handle.listen(backlog || 511);

...

  defaultTriggerAsyncIdScope(this[async_id_symbol],
                             process.nextTick,
                             emitListeningNT, // 触发`listening`事件
                             this);
}
  1. 绑定地址和端口;
  2. 触发listening事件。

进阶

调用onconnection函数

node在C++层调用js层的onconnection函数,并传入底层的socket,完成�底层socket与node net模块的连接与请求打通。
onconnection函数内部主要做了两件事:

  1. 构建nodejs层的net.Socket对象;
  2. 并触发connection事件。
function onconnection(err, clientHandle) {
  const handle = this;
  const self = handle[owner_symbol];
...

  const socket = new Socket({
    handle: clientHandle,
    allowHalfOpen: self.allowHalfOpen,
    pauseOnCreate: self.pauseOnConnect,
    readable: true,
    writable: true
  });

...

  self._connections++; // 记录已建立的连接数量
  socket.server = self; // 额外赋值,即可以通过socket反向获取服务对象
  socket._server = self;

  self.emit('connection', socket);
...
}

参考

  1. 通过Node.js的Cluster模块源码,深入PM2原理
  2. Nodejs cluster模块深入探究

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions