详解两个Node.js进程是如何通信

目录
  • 前言
  • 不同电脑上的两个 Node.js 进程间通信
    • 使用 TCP 套接字
    • 使用 HTTP 协议
  • 同一台电脑上两个 Node.js 进程间通信
    • 使用内置 IPC 通道
    • 使用自定义管道
  • 总结

前言

两个 Node.js 进程之间如何进行通信呢?这里要分两种场景:

  1. 不同电脑上的两个 Node.js 进程间通信
  2. 同一台电脑上两个 Node.js 进程间通信

对于第一种场景,通常使用 TCP 或 HTTP 进行通信,而对于第二种场景,又分为两种子场景:

  1. Node.js 进程和自己创建的 Node.js 子进程通信
  2. Node.js 进程和另外不相关的 Node.js 进程通信

前者可以使用内置的 IPC 通信通道,后者可以使用自定义管道,接下来进行详细介绍:

不同电脑上的两个 Node.js 进程间通信

要想进行通信,首先得搞清楚如何标识网络中的进程?网络层的 ip 地址可以唯一标识网络中的主机,而传输层的协议和端口可以唯一标识主机中的应用程序(进程),这样利用三元组(ip 地址,协议,端口)就可以标识网络的进程了。

使用 TCP 套接字

TCP 套接字(socket)是一种基于 TCP/IP 协议的通信方式,可以让通过网络连接的计算机上的进程进行通信。一个作为 server 另一个作为 client,server.js 代码如下:

const net = require('net')
const server = net.createServer(socket => {
  console.log('socket connected')
  socket.on('close', () => console.log('socket disconnected'))
  socket.on('error', err => console.error(err.message))
  socket.on('data', data => {
    console.log(`receive: ${data}`)
    socket.write(data)
    console.log(`send: ${data}`)
  })
})
server.listen(8888)

client.js 代码:

const net = require('net')
const client = net.connect(8888, '192.168.10.105')

client.on('connect', () => console.log('connected.'))
client.on('data', data => console.log(`receive: ${data}`))
client.on('end', () => console.log('disconnected.'))
client.on('error', err => console.error(err.message))

setInterval(() => {
  const msg = 'hello'
  console.log(`send: ${msg}`)
  client.write(msg)
}, 3000)

运行效果:

$ node server.js
client connected
receive: hello
send: hello

$ node client.js
connect to server
send: hello
receive: hello

使用 HTTP 协议

因为 HTTP 协议也是基于 TCP 的,所以从通信角度看,这种方式本质上并无区别,只是封装了上层协议。server.js 代码为:

const http = require('http')
http.createServer((req, res) => res.end(req.url)).listen(8888)

client.js 代码:

const http = require('http')
const options = {
  hostname: '192.168.10.105',
  port: 8888,
  path: '/hello',
  method: 'GET',
}
const req = http.request(options, res => {
  console.log(`statusCode: ${res.statusCode}`)
  res.on('data', d => process.stdout.write(d))
})
req.on('error', error => console.error(error))
req.end()

运行效果:

$ node server.js
url /hello

$ node client.js
statusCode: 200
hello

同一台电脑上两个 Node.js 进程间通信

虽然网络 socket 也可用于同一台主机的进程间通讯(通过 loopback 地址 127.0.0.1),但是这种方式需要经过网络协议栈、需要打包拆包、计算校验和、维护序号和应答等,就是为网络通讯设计的,而同一台电脑上的两个进程可以有更高效的通信方式,即 IPC(Inter-Process Communication),在 unix 上具体的实现方式为 unix domain socket,这是服务器端和客户端之间通过本地打开的套接字文件进行通信的一种方法,与 TCP 通信不同,通信时指定本地文件,因此不进行域解析和外部通信,所以比 TCP 快,在同一台主机的传输速度是 TCP 的两倍。

使用内置 IPC 通道

如果是跟自己创建的子进程通信,是非常方便的,child_process模块中的 fork 方法自带通信机制,无需关注底层细节,例如父进程 parent.js 代码:

const fork = require("child_process").fork
const path = require("path")
const child = fork(path.resolve("child.js"), [], { stdio: "inherit" });
child.on("message", (message) => {
  console.log("message from child:", message)
  child.send("hi")
})

子进程 child.js 代码:

process.on("message", (message) => {
  console.log("message from parent:", message);
})

if (process.send) {
  setInterval(() => process.send("hello"), 3000)
}

运行效果如下:

$ node parent.js
message from child: hello
message from parent: hi
message from child: hello
message from parent: hi

使用自定义管道

如果是两个独立的 Node.js 进程,如何建立通信通道呢?在 Windows 上可以使用命名管道(Named PIPE),在 unix 上可以使用 unix domain socket,也是一个作为 server,另外一个作为 client,其中 server.js 代码如下:

const net = require('net')
const fs = require('fs')

const pipeFile = process.platform === 'win32' ? '\\\\.\\pipe\\mypip' : '/tmp/unix.sock'

const server = net.createServer(connection => {
  console.log('socket connected.')
  connection.on('close', () => console.log('disconnected.'))
  connection.on('data', data => {
    console.log(`receive: ${data}`)
    connection.write(data)
    console.log(`send: ${data}`)
  })
  connection.on('error', err => console.error(err.message))
})

try {
  fs.unlinkSync(pipeFile)
} catch (error) {}

server.listen(pipeFile)

client.js 代码如下:

const net = require('net')

const pipeFile = process.platform === 'win32' ? '\\\\.\\pipe\\mypip' : '/tmp/unix.sock'

const client = net.connect(pipeFile)
client.on('connect', () => console.log('connected.'))
client.on('data', data => console.log(`receive: ${data}`))
client.on('end', () => console.log('disconnected.'))
client.on('error', err => console.error(err.message))

setInterval(() => {
  const msg = 'hello'
  console.log(`send: ${msg}`)
  client.write(msg)
}, 3000)

运行效果:

$ node server.js
socket connected.
receive: hello
send: hello

$ node client.js
connected.
send: hello
receive: hello

总结

到此这篇关于两个Node.js进程是如何通信的文章就介绍到这了,更多相关两个Node.js进程通信内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解从Node.js的child_process模块来学习父子进程之间的通信

    child_process模块提供了和popen(3)一样的方式来产生自进程,这个功能主要是通过child_process.spawn函数来提供的: const spawn = require('child_process').spawn; const ls = spawn('ls', ['-lh', '/usr']); ls.stdout.on('data', (data) => { console.log(`stdout: ${data}`); }); ls.stderr.on('data'

  • node 利用进程通信实现Cluster共享内存

    Node.js的标准API没有提供进程共享内存,然而通过IPC接口的send方法和对message事件的监听,就可以实现一个多进程之间的协同机制,通过通信来操作共享内存. ##IPC的基本用法: // worker进程 发送消息 process.send('读取共享内存'); // master进程 接收消息 -> 处理 -> 发送回信 cluster.on('online', function (worker) { // 有worker进程建立,即开始监听message事件 worker.o

  • 详解两个Node.js进程是如何通信

    目录 前言 不同电脑上的两个 Node.js 进程间通信 使用 TCP 套接字 使用 HTTP 协议 同一台电脑上两个 Node.js 进程间通信 使用内置 IPC 通道 使用自定义管道 总结 前言 两个 Node.js 进程之间如何进行通信呢?这里要分两种场景: 不同电脑上的两个 Node.js 进程间通信 同一台电脑上两个 Node.js 进程间通信 对于第一种场景,通常使用 TCP 或 HTTP 进行通信,而对于第二种场景,又分为两种子场景: Node.js 进程和自己创建的 Node.j

  • 详解如何使用Node.js实现热重载页面

    前言 前不久我结合browser-sync+gulp+gulp-nodemon实现了一款生产环境热更新(我之前理解有点偏差,应该定义为热更新,不是热重载)的项目脚手架,那么,今天我们将使用Node.js实现一个热重载页面. 那么,我今天就总结一下吧,以防止大家也跟我一样. 热重载 所谓热重载就是页面每次改动,不需要手动去刷新,可自动刷新. 热更新 浏览器的无刷新更新,允许在运行时替换,添加,删除各种模块,而无需进行完全刷新重新加载整个页面. 目的:加快开发速度,所以只适用于开发环境下使用. 思路

  • 详解如何在Node.js的httpServer中接收前端发送的arraybuffer数据

    最近使用了protobuf进行数据交互,发送在node.js接收前端的二进制数据出现了数据错误等问题.后来发现思路上面的问题,在req.on('data',()=>{})事件中的处理不适当才引发数据错乱.借此发 我先直接贴正确接收二进制数据代码 const server = http.createServer((req, res) => { if(req.method==='OPTIONS'){ res.setHeader("Access-Control-Allow-Origin&q

  • 详解Wondows下Node.js使用MongoDB的环境配置

    为了保存网站的用户数据和业务数据,通常需要一个数据库.MongoDB和Node.js特别般配,因为MongoDB是基于文档的非关系型数据库,文档是按BSON(JSON的轻量化二进制格式)存储的,增删改查等管理数据库的命令和JavaScript语法很像.如果你在Node.js里访问MongoDB的数据,会有我们是一家人的感觉,特别亲切. 我也准备使用MongoDB来作为我的数据库. MongoDB使用集合(collection)和文档(document)来描述和存储数据,collection就相当

  • 详解axios在node.js中的post使用

    前言: 最近因为做的东西需要用到网络请求库,之前接触过的只有request,很强大好用.但是这个项目中需要用到Promise,我又不想重新封装,于是选择了另一款库axios. 在node中,axios的get请求加上原生支持的Promise语法使用起来很方便,很丝滑,但是后面碰到了一个需求,就是要向另一个服务器post数据,并且这个数据是以form-data的形式post过去的,这时,问题就出现了. 问题: 当我想在node中使用axios以post的方式发送一张图片给某个server时,最先我

  • 详解如何使用Node.js编写命令工具——以vue-cli为例

    vue-cli全局安装之后,提供了vue命令和vue init.vue list.vue build三个子命令,通过命令可以搭建基于vue.js的脚手架项目.本文简单介绍一下这些命令是如何实现的. vue-cli的项目目录 如下图,由之前文章介绍,npm安装过程中,可以利用package.json中bin字段的配置,将bin目录下的命令文件软连到全局命令.也就是说在/usr/local/bin下生成了四个软连命令:vue.vue-build.vue-list.vue-init. vue命令的源码

  • 详解如何使用node.js的开发框架express创建一个web应用

    搭建环境 1.安装Express 按键:Windows+R=>输入cmd,打开命令行,输入 npm install -g express@3 我们需要用全局模式安装Express,因为只有这样,我们才能在命令行中使用它 注意:这里我只选用Express 3.x版本,要是你对Express3x版本熟悉了的话,你只需看一下Migrating from 3.x to 4.x 的文档即可过渡到Express 4.x 2.新建一个工程 继续打开命令行,输入 express -e murenziwei 注意

  • 详解一些适用于Node.js的命名约定

    序言 There are only two hard things in Computer Science: cache invalidation and naming things. -- Phil Karlton 我乔鲁诺·乔巴拿有一个梦想,便是要成为程序员巨星.但如果你看过我写的代码,便知道我还远远够不上"巨星"二字.我的代码中有许多不一致的命名: 常量的命名时而是全大写的(如WAIT_CONFIRM),时而是全小写的: 某个项目大部分命名用的是camel case(如TaskC

  • Node.js进程管理之子进程详解

    一.理论 之前看多进程这一章节时发现这块东西挺多,写Process模块的时候也有提到,今天下午午休醒来静下心来好好的看了一遍,发现也不是太难理解. Node.js是单线程的,对于现在普遍是多处理器的机器是一种浪费,怎么能利用起来呢?于是child_process模块出现了.child_process模块可以在其他进程上产生.派生,并执行工作. child_process模块提供了一个ChildProcess的新类,它可以作为从父进程访问子进程的表示形式.Process模块也是ChildProce

  • Node.js进程管理之Process模块详解

    在前面Node.js事件运行机制也有提到,Node.js应用在单个线程运行,但是现在大部分服务器都是多处理器,为了方便使用多个进程,Node.js提供了3个模块.Process模块提供了访问正在运行的进程.child_process模块可以创建子进程,并与他们通信.cluster模块提供了实现共享相同端口的集群服务能力,允许多个请求同时处理. 一.Process模块 Process模块是一个无须使用require()就可以从node.js应用程序进行访问的全局对象. 二.进程I/O管道 Proc

随机推荐