Node.js UDP通信 dgram 组播

先说一些大家喜闻乐见的废话

UDP是一种速度快,但可靠性低的一种通信方式,音视频,游戏,基本都在使用它,更具体的废话比如说OSI七层模型之类的就不多说了,因为计网都教过

在Node.js中,常使用dgram这个库做UDP通信,dgram是由node官方封装的,无需安装,require引入使用即可

dgram 数据报 | Node.js v22 文档

UDP在日常中分为两种使用方式,一种是单播,一种是组播(多播)

单播是指,A设备只能跟B设备通信,相反则不行,类似于单工

组播(广播)是指,AB设备互相都能通信,没有限制

使用组播时,接收消息的端口和发送消息的端口要一致,也就是bind和send函数中传递的端口一致,在ip地址方面是组播地址就行,我这边因为是局域网通信,所以用了224.0.0.5来通过路由器实现局域网内组播

下面是组播的代码,通用性还是比较高的,避免因本地有多张网卡分属于不同的IP段,造成消息发出去接不到的情况,比如说我本机是192.168.124.55,局域网其他电脑也都是192.168.124开头的,虚拟网卡是192.168.54.1,本机是有可能连到虚拟网卡并且从它的IP段发送数据的,就会造成一种看着是本机发送数据了,但是同局域网的电脑收不到的情况

javascript 复制代码
const PORT = 20000;
const MULTICAST_ADDR = "224.0.0.5";
const BaseSourceData = require("../pojo/index.js");

const dgram = require("dgram");
const process = require("process");
const CWS = require("../ws/index.js");
const cws = CWS;

let arr = [];
const getLocalIPV4 = (ver = 4) => {
  const interfaces = require("os").networkInterfaces();
  let ips = [];
  for (let netDev in interfaces) {
    for (let netProt of interfaces[netDev]) {
      if (
        netProt.family === `IPv${ver}` &&
        !netProt.internal &&
        netProt.address !== "127.0.0.1"
      ) {
        ips.push(netProt.address);
      }
    }
  }
  return ips;
};

getLocalIPV4().forEach((item, index) => {
  console.log("🚀 ~ getLocalIPV4 ~ item: server", item);
  arr[index] = dgram.createSocket("udp4", { type: "udp4", reuseAddr: true });

  arr[index].bind(PORT, item);

  arr[index].on("listening", function () {
    arr[index].addMembership(MULTICAST_ADDR);
    arr[index].setBroadcast(true);
    setInterval(() => {
      sendMessage(address);
    }, 2500);
    const address = arr[index].address();
    console.log(
      `UDP socket listening on ${address.address}:${address.port} pid: ${
        process.pid
      }`
    );
  });

  function sendMessage(address) {
    const findUserObj = new BaseSourceData({
      time: Date.now(),
      userName: cws.userName,
      startTime: cws.startTime,
      avatar: cws.avatar,
    });
    const message = Buffer.from(JSON.stringify(findUserObj));
    arr[index].send(
      message,
      0,
      message.length,
      PORT,
      MULTICAST_ADDR,
      function () {
        console.info(`Sending message "${message}"`);
      }
    );
  }

  arr[index].on("message", function (message, rinfo) {
    if (getLocalIPV4().some((ip) => ip === rinfo.address)) {
      return;
    }
    let tempObj = JSON.parse(message.toString());
    tempObj.data.ip = rinfo.address;
    const findUserObj = JSON.stringify(tempObj);
    if (!!cws.wsObj) {
      cws.wsObj.send(findUserObj);
    }
    console.info(`Message from: ${rinfo.address}:${rinfo.port} - ${message}`);
  });
});
相关推荐
Nueuis33 分钟前
微信小程序前端面经
前端·微信小程序·小程序
FreeBuf_2 小时前
最新研究揭示云端大语言模型防护机制的成效与缺陷
网络·安全·语言模型
_r0bin_3 小时前
前端面试准备-7
开发语言·前端·javascript·fetch·跨域·class
IT瘾君3 小时前
JavaWeb:前端工程化-Vue
前端·javascript·vue.js
potender3 小时前
前端框架Vue
前端·vue.js·前端框架
站在风口的猪11084 小时前
《前端面试题:CSS预处理器(Sass、Less等)》
前端·css·html·less·css3·sass·html5
程序员的世界你不懂4 小时前
(9)-Fiddler抓包-Fiddler如何设置捕获Https会话
前端·https·fiddler
MoFe14 小时前
【.net core】天地图坐标转换为高德地图坐标(WGS84 坐标转 GCJ02 坐标)
java·前端·.netcore
去旅行、在路上5 小时前
chrome使用手机调试触屏web
前端·chrome
Aphasia3115 小时前
模式验证库——zod
前端·react.js