NodeJs-UDP/datagram

class UDP/datagram

Node.js 的 dgram 模块提供了 UDP(用户数据报协议)实现,允许我们通过 Datagram Sockets 进行无连接通信。UDP 是一种无连接、面向数据报的协议,与 TCP 不同,它不提供传输保障,适合对速度有要求的应用场景,如流媒体、在线游戏等。

dgram 模块中,Datagram Sockets 主要用于发送和接收数据报。以下是 dgram 模块的相关属性、方法以及详细使用方式,涵盖各个方面。


1. 引入 dgram 模块

首先,需要将 dgram 模块引入到你的项目中:

const dgram = require('dgram');

2. 创建 UDP Socket

使用 dgram.createSocket() 来创建一个 UDP socket,它将返回一个 dgram.Socket 对象,用于接收或发送数据。

const socket = dgram.createSocket(type, [callback]);

参数:

  • type:指定 socket 使用的协议类型。可以是 'udp4'(IPv4)或 'udp6'(IPv6)。
  • callback:可选的回调函数,当 socket 接收到消息时调用。

示例:

const socket = dgram.createSocket('udp4');

在这个例子中,我们创建了一个基于 IPv4 的 UDP socket。


3. Socket 的事件

dgram.Socket 类继承自 EventEmitter,提供了一些重要的事件,用于处理 UDP 通信过程中的不同状态和情况。

事件列表:

  1. 'message':当 socket 接收到消息时触发。

    • 参数
      • msg:接收到的消息(Buffer 对象)。
      • rinfo:包含远程信息的对象(addressfamilyportsize)。
    socket.on('message', (msg, rinfo) => {
      console.log(`Received message: ${msg} from ${rinfo.address}:${rinfo.port}`);
    });
    
  2. 'listening':当 socket 准备好接收数据时触发。

    socket.on('listening', () => {
      const address = socket.address();
      console.log(`Socket listening on ${address.address}:${address.port}`);
    });
    
  3. 'error':当发生错误时触发。

    • 参数
      • err:错误对象。
    socket.on('error', (err) => {
      console.error(`Socket error:\n${err.stack}`);
      socket.close();
    });
    
  4. 'close':当 socket 被关闭时触发。

    socket.on('close', () => {
      console.log('Socket closed');
    });
    

4. Socket 方法

dgram.Socket 提供了多种方法来发送数据、关闭 socket 和控制其行为。

4.1 socket.bind([port], [address], [callback])

将 socket 绑定到指定的 portaddress。如果没有指定 port,系统将分配一个随机端口。如果没有指定 address,默认绑定到 '0.0.0.0''::'(取决于使用的 IP 版本)。

  • port:要绑定的端口号。
  • address:要绑定的 IP 地址(如 'localhost''127.0.0.1''0.0.0.0''::1')。
  • callback:绑定成功时调用的回调函数。
socket.bind(12345, 'localhost', () => {
  console.log('Socket bound to port 12345');
});

4.2 socket.send(msg, [offset], [length], port, address, [callback])

发送数据报到指定的 portaddress

  • msg:要发送的消息,可以是 Buffer、字符串或数组。
  • offset:可选,指定从 msg 中读取数据的开始位置。
  • length:可选,要发送的字节长度。
  • port:目标主机的端口号。
  • address:目标主机的 IP 地址或域名。
  • callback:可选,数据发送后调用的回调函数。
const message = Buffer.from('Hello UDP');
socket.send(message, 0, message.length, 12345, 'localhost', (err) => {
  if (err) console.error('Send error:', err);
  console.log('Message sent');
});

4.3 socket.close([callback])

关闭 socket。当 socket 被关闭时,'close' 事件将会触发。可选的 callback 将在关闭后调用。

socket.close(() => {
  console.log('Socket closed');
});

4.4 socket.setBroadcast(flag)

启用或禁用广播消息。如果 flagtrue,socket 可以发送 UDP 广播消息。

socket.setBroadcast(true);

4.5 socket.setTTL(ttl)

设置 IP 数据报的生存时间(TTL,Time to Live),默认值为 64。ttl 是一个 1 到 255 的数字,表示该数据报在网络中的最大跳数。

socket.setTTL(128);

4.6 socket.setMulticastTTL(ttl)

设置组播数据报的 TTL(Time to Live)。ttl 是一个 1 到 255 的数字。

socket.setMulticastTTL(64);

4.7 socket.setMulticastLoopback(flag)

启用或禁用组播环回。如果 flagtrue,本地回送(loopback)将会启用,这意味着组播数据报也会发送到发送端的本地接口。

socket.setMulticastLoopback(true);

4.8 socket.addMembership(multicastAddress, [multicastInterface])

加入一个指定的组播地址。可选的 multicastInterface 是要使用的网络接口的 IP 地址。

socket.addMembership('239.255.255.250'); // 加入某个组播组

4.9 socket.dropMembership(multicastAddress, [multicastInterface])

离开一个组播地址。

socket.dropMembership('239.255.255.250'); // 离开某个组播组

4.10 socket.ref()

保持 Node.js 事件循环,阻止其退出。如果 socket 是唯一活跃的事件源,调用此方法将允许事件循环保持运行。

socket.ref();

4.11 socket.unref()

允许 Node.js 事件循环退出,即使此 socket 仍然打开。如果 socket 是唯一活跃的事件源,调用此方法将允许事件循环退出。

socket.unref();

5. UDP 广播

UDP 广播允许将数据报发送到一个网络中的所有设备。

要发送广播消息,需要启用广播:

socket.setBroadcast(true);

然后发送到广播地址(如 255.255.255.255 或某个子网内的地址):

const message = Buffer.from('Broadcast message');
socket.send(message, 0, message.length, 41234, '255.255.255.255', (err) => {
  if (err) console.error('Broadcast error:', err);
  console.log('Broadcast message sent');
});

6. UDP 组播

UDP 组播用于将消息发送给多个订阅特定组播地址的设备。组播地址的范围通常在 224.0.0.0239.255.255.255 之间。

加入组播组:

socket.addMembership('239.255.255.250');

设置组播 TTL(生存时间):

socket.setMulticastTTL(128);

启用组播回送:

socket.setMulticastLoopback(true);

7. 示例:完整的 UDP 服务器与客户端

服务器端:

const dgram = require('dgram');
const server = dgram.createSocket('udp4');

server.on('message', (msg, rinfo) => {
  console.log(`Server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
});

server.on('listening', () => {
  const address = server.address();
  console.log(`Server listening on ${address.address}:${address.port}`);
});

server.bind(41234); // 服务器绑定端口

客户端:

const dgram = require('dgram');
const client = dgram.createSocket('

udp4');

const message = Buffer.from('Hello, UDP server!');
client.send(message, 0, message.length, 41234, 'localhost', (err) => {
  if (err) console.error('Send error:', err);
  client.close();
});

8. UDP 使用场景

  • 实时应用(如视频流、音频流等)
  • 在线游戏
  • IoT 设备通信
  • 广播消息和组播消息
  • 网络发现协议(如 SSDP)

UDP 的优势在于速度快、开销低,但它没有像 TCP 那样的可靠性保障,因此适合不需要可靠传输或有自己纠错机制的应用场景。


总结来说,dgram 模块提供了强大的工具来构建基于 UDP 的通信应用。

评论区
评论列表
menu