nodejs如何实现基于window File Mapping的进程间通信(IPC)

本文介绍了一种高效地将C++代码产生的图像数据传输到Node.js WEB页面的技术方案,通过windowFileMapping实现内存共享,以及利用koa2框架和canvas双缓冲技术确保图像平滑显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     笔者碰到这样的需求,即如何将C++代码产生的图像数据高速的渲染到由Nodejs编写的WEB页面上,而且图像数据以每秒几十帧以上的速度产生,WEB界面显示要平滑连续不卡顿。

      针对这样的需求,笔者做了下调研,确定了需要解决如下的关键技术点:

  1. 如何在C++代码和nodejs代码之间高速交换数据。
  2. 如何在浏览器前端和Nodejs后端传输和渲染图像数据

如何在C++代码和nodejs代码之间高速交换数据

     采用window File Mapping来进行内存共享,实现进程间通信,nodejs可以通过编写addon(插件)的方式来访问window File Mapping 的API。编写nodejs addon插件不是一件容易的事情,好在目前有一种node-addon-api技术可大大简化插件的开发,只要具备一定的C++知识即可编写,具体样例可参考:

GitHub - nodejs/node-addon-api: Module for using Node-API from C++Module for using Node-API from C++. Contribute to nodejs/node-addon-api development by creating an account on GitHub.https://github.com/nodejs/node-addon-api#examples    关于window File Mapping的API使用则很简单,微软官方提供了简单的示例,只需要将这个示例按照node-addon-api的接口要求进行改造一下即可。关于window File Mapping的使用可参考

Creating Named Shared Memory - Win32 apps | Microsoft LearnTo share data, multiple processes can use memory-mapped files that the system paging file stores.icon-default.png?t=M85Bhttps://learn.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory    根据上面所述,笔者编写了一个demo,生成addon, 在nodejs代码里可以方便调用,例如进程生产数据的代码类似如下:

var addon = require('../build/Release/addon')
var env = require('./env')

var mapName = env.file_mapping_name;
var bufSize = env.image_width*env.image_height;

var fileMap = new addon.FileMap();
//直接返回封装好的Buffer对象
var buf = fileMap.create(mapName,bufSize);
buf[0] = 1;
buf[1] = 2;

    这个插件的create方法创建了FileMapping对象并返回Buffer对象,这个方法没有进行内存拷贝操作,是直接引用并封装到javascript里的Buffer对象里,可以利用Buffer对象的方法直接进行数据操作。

   而消费者进程则也可以用该addon获取共享内存,消费数据,代码类似如下

var addon = require('../build/Release/addon')
var env = require('./env')

var mapName = env.file_mapping_name;
var bufSize = env.image_width*env.image_height;
var fileMap = new addon.FileMap();

var buf = fileMap.open(mapName,bufSize,0);
if(buf)
{
   console.log(`buf size=${buf.length}`);
   var value = buf[0];
}

如何在浏览器前端和Nodejs后端传输和渲染图像数据

    笔者使用了koa2作为Nodejs的web框架,使用上面提到的插件来获取图像数据,并通过web api返回二进制流数据给前端,代码示例如下:

router.get('/image',async (ctx, next) =>{
  const fileMap = new addon.FileMap();
  var buf = fileMap.open(env.file_mapping_name, env.image_height*env.image_width,0);
  if(!buf)
  {
        console.log('file mapping is not opened');
        ctx.throw(500);
  }

  ctx.set("Content-Type", "application/octet-stream");
  ctx.response.body = buf;
})

 而前端页面则采用canvas的双缓冲来绘制图像,并使用requestAninationFrame方法来起到平滑播放动画的效果,代码示例如下:


    const downloadData = async () => {
       const resp = await axios.get('/image',{responseType: 'arraybuffer'});
       return resp.data;
    }
    
    const sleep = (interval) => {
      return new Promise(resolve => {
        setTimeout(resolve, interval);
     })
    }

    var canvas = document.querySelector('#my-canvas');
    var context = canvas.getContext('2d');
      // to increase performance createImageData method 
      // should be executed once e.g. before drawing
      var image = context.createImageData(canvas.width, canvas.height);
      var data = image.data;
      var dataView = new Uint32Array(data.buffer);
      const height = canvas.height;
      const width = canvas.width;
      const byteLength = height*width;

      function drawPixel(i, value) {
            dataView[i] =
            (255   << 24) |	// alpha
            (value << 16) |	// blue
            (value <<  8) |	// green
             value;		// red
       } 
       
       function swapBuffer() {
          context.putImageData(image, 0, 0);
        }


    const showData = async () => {
      var buf = await downloadData();

       if(buf.byteLength < byteLength)
       {
           console.log("error:downloaded buffer's size is smaller than canvas's size");
           return;
       }
      var bufView = new Uint8Array(buf);     

      var t1 = new Date();
       
        for(var y = 0; y < height; ++y) {
          for(var x = 0; x < width; ++x) {
            var index = y*height + x;
            var gray = bufView[index];
            //var color = { r : gray, g: gray, b:gray, a:255 };
            drawPixel(index, gray);
        }
      }

        swapBuffer();

        var t2 = new Date();
        var dt = t2 - t1;
        console.log('elapsed time = ' + dt + ' ms');
    }

    const animate = () => {
      showData().then( () =>
        window.requestAnimationFrame(animate)
       ).catch(err => console.log(err));
    }
    

    window.requestAnimationFrame(animate)

整个demo完整代码示例可访问码云

node-filemap-buf: 基于node-addon-api编写的插件,通过调用window file mapping的api来获取内存,实现进程间内存共享https://gitee.com/bellcode/node-filemap-buf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值