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}`);
  });
});
相关推荐
Tim风声(网络工程师)18 分钟前
排查内网互联网访问流程
运维·服务器·网络
kyriewen33 分钟前
百度用6%成本碾压硅谷?中国AI把性价比玩明白了
前端·百度·ai编程
kyriewen1 小时前
你还在手动敲命令部署?GitHub Actions 让你 push 即上线,摸鱼时间翻倍
前端·面试·github
Csvn3 小时前
Pinia 状态管理
前端
不减20斤不改头像3 小时前
手机一句话开发贪吃蛇!TRAE SOLO 移动端 AI 编程实测
前端·后端
一袋米扛几楼983 小时前
【网络】网络规划与底层通信:自顶向下方法论 (Top-Down Methodology) 全解析
网络·工程
xuankuxiaoyao3 小时前
Vue.js实践-组件基础下
前端·javascript·vue.js
liulilittle3 小时前
TCP BBR 拥塞控制模块编译
网络·网络协议·tcp/ip
一棵白菜3 小时前
Claude Code + Amazon Bedrock 使用指南
前端
wangl_924 小时前
Modbus RTU 与 Modbus TCP 深入指南-功能码与数据模型
网络·网络协议·tcp/ip·tcp·modbus·rtu