阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      Node.js child_process subprocess.send

      Node.js child_process subprocess.send(message[, sendHandle[, options]][, callback]) 版本历史

      版本变更
      v5.8.0The options parameter, and the keepOpen option in particular, is supported now.
      v5.0.0This method returns a boolean for flow control now.
      v4.0.0The callback parameter is supported now.
      v0.5.9新增于: v0.5.9
      • message < Object>
      • sendHandle < Handle>
      • options < Object>
        • keepOpen < boolean> 当设为 true 时,发送进程的 socket 会保持打开。默认值: false`。
      • callback < Function>
      • 返回: < boolean>

      当父进程和子进程之间建立了一个 IPC 通道时(例如,使用 child_process.fork()), subprocess.send() 方法可用于发送消息到子进程。 当子进程是一个 Node.js 实例时,消息可以通过 ‘message’ 事件接收。

      消息通过序列化和解析进行传递,接收到消息可能跟发送的不完全一样。

      例子,父进程脚本如下:

      const cp = require('child_process');
      const n = cp.fork(`${__dirname}/sub.js`);
      
      n.on('message', (m) => {
        console.log('父进程收到消息', m);
      });
      
      // 使子进程输出: 子进程收到消息 { hello: 'world' }
      n.send({ hello: 'world' });
      

      子进程脚本 ‘sub.js’ 如下:

      process.on('message', (m) => {
        console.log('子进程收到消息', m);
      });
      
      // 使父进程输出: 父进程收到消息 { foo: 'bar', baz: null }
      process.send({ foo: 'bar', baz: NaN });
      

      Node.js 中的子进程有一个自己的 process.send() 方法,允许子进程发送消息回父进程。

      当发送一个 {cmd: ‘NODE_foo’} 消息时,是一个特例。 cmd 属性中包含 NODE_ 前缀的消息是预留给 Node.js 核心代码内部使用的,不会触发子进程的 ‘message’ 事件。 而是,这种消息可使用 process.on(‘internalMessage’) 事件触发,且被 Node.js 内部消费。 应用程序应避免使用这种消息或监听 ‘internalMessage’ 事件。

      可选的 sendHandle 参数可能被传给 subprocess.send(),它用于传入一个 TCP 服务器或 socket 对象给子进程。 子进程会接收对象作为第二个参数,并传给注册在 ‘message’ 事件上的回调函数。 socket 上接收或缓冲的任何数据不会被发送给子进程。

      可选的 callback 是一个函数,它在消息发送之后、子进程收到消息之前被调用。 该函数被调用时只有一个参数:成功时是 null,失败时是一个 Error 对象。

      如果没有提供 callback 函数,且消息没被发送,则一个 ‘error’ 事件将被 ChildProcess 对象触发。 这是有可能发生的,例如当子进程已经退出时。

      如果通道已关闭,或当未发送的消息的积压超过阈值使其无法发送更多时, subprocess.send() 会返回 false。 除此以外,该方法返回 true。 callback 函数可用于实现流量控制。

      例子:发送 server 对象

      sendHandle 参数可用于将一个 TCP server 对象句柄传给子进程,如下所示:

      const subprocess = require('child_process').fork('subprocess.js');
      
      // 开启 server 对象,并发送该句柄。
      const server = require('net').createServer();
      server.on('connection', (socket) => {
        socket.end('被父进程处理');
      });
      server.listen(1337, () => {
        subprocess.send('server', server);
      });
      

      子进程接收 server 对象如下:

      process.on('message', (m, server) => {
        if (m === 'server') {
          server.on('connection', (socket) => {
            socket.end('被子进程处理');
          });
        }
      });
      

      当服务器在父进程和子进程之间是共享的,则一些连接可被父进程处理,另一些可被子进程处理。

      上面的例子使用了一个 net 模块创建的服务器,而 dgram 模块的服务器使用完全相同的工作流程,但它监听一个 ‘message’ 事件而不是 ‘connection’ 事件,且使用 server.bind 而不是 server.listen()。 目前仅 UNIX 平台支持这一点。

      例子:发送 socket 对象

      同样, sendHandle 参数可用于将一个 socket 句柄传给子进程。 以下例子衍生了两个子进程,分别用于处理 “normal” 连接或优先处理 “special” 连接:

      const { fork } = require('child_process');
      const normal = fork('subprocess.js', ['normal']);
      const special = fork('subprocess.js', ['special']);
      
      // 开启 server,并发送 socket 给子进程。
      // 使用 `pauseOnConnect` 防止 socket 在被发送到子进程之前被读取。
      const server = require('net').createServer({ pauseOnConnect: true });
      server.on('connection', (socket) => {
      
        // 特殊优先级。
        if (socket.remoteAddress === '74.125.127.100') {
          special.send('socket', socket);
          return;
        }
        // 普通优先级。
        normal.send('socket', socket);
      });
      server.listen(1337);
      

      subprocess.js 会接收到一个 socket 句柄,并作为第二个参数传给事件回调函数:

      process.on('message', (m, socket) => {
        if (m === 'socket') {
          if (socket) {
            // 检查客户端 socket 是否存在。
            // socket 在被发送与被子进程接收这段时间内可被关闭。
            socket.end(`请求被 ${process.argv[2]} 优先级处理`);
          }
        }
      });
      

      一旦一个 socket 已被传给了子进程,则父进程不再能够跟踪 socket 何时被销毁。 为了表明这个, .connections 属性会变成 null。 当发生这种情况时,建议不要使用 .maxConnections。

      建议在子进程中的任何 message 处理程序都需要验证 socket 是否存在,因为连接可能会在它在发送给子进程的这段时间内被关闭。


      更多内容请参考:Node.js child_process 子进程,或者通过 点击对应菜单 进行查看;


      目录
      目录