Nodejs之dgram模块的理解

1,200 阅读4分钟

在上一篇文章Nodejs之net模块的理解中,我们介绍了NodeJS创建基于TCP协议通信的服务器和客户端的使用。本篇文章继续带领大家理解位于传输控制协议的另一个重要组成-UDP。

1. dgram模块的作用

Nodejs核心模块dgram提供开发者创建UDP服务器和客户端的通信能力。

2. 关于UDP协议

UDP(User Datagram Protocol)用户数据报协议,是OSI参考模型中一种无连接的传输层协议,提供面向服务简单不可靠的信息传送服务。

2.1 TCP与UDP特点对比分析

特点TCPUDP
连接面向连接无连接
可靠传输可靠不可靠
传输效率
通信方式一对一单播、组播、广播

从UDP协议特点可看出,由于通信前不需要进行双方建立连接,传输效率高,适用于对实时性要求较高的应用场景。

2.2 UDP单播

单播,即地址为单一目标的传播方式,用于两个主机之间的端对端通信。

单播优缺点:

  • 服务器及时响应客户端请求;
  • 服务器针对每个客户端不同请求提供不同数据,提供个性化服务;
  • 由于服务器需要向网络中每一个客户端提供请求响应处理,造成服务端压力过大
2.3 UDP广播

广播,即地址为网络中所有目标的传播方式,广播与单播的区别就是IP不同,广播使用广播地址(根据ip地址和子网掩码进行与计算得到),将消息发送到某一广播网络上的所有目标设备;值得注意广播不会被路由设备转发。简单理解就是向广播网内所有设备喊话,需要指名端口号,不可能接收者的所有端口都接受广播内容。

广播优缺点:

  • 由于服务器不用向每个客户机单独发送数据,所以服务器流量负载比较低;
  • 无法针对每个客户的要求和时间及时提供个性化服务;

2.4 UDP组播 组播,即对同一网络中的设备进行分组,只有一组内的网络设备可以收到数据,在广域网上组播的时候,其中的交换机和路由器只向需要获取数据的主机复制并转发数据。主机可以向路由器请求加入或退出某个组,网络中的路由器和交换机有选择地复制并传输数据,将数据仅仅传输给组内的主机。

组播优缺点:

  • 需要相同数据流的客户端加入相同的组共享一条数据流,节省了服务器的负载。
  • 由于组播协议是根据接受者的需要对数据流进行复制转发,所以服务端的服务总带宽不受客户接入端带宽的限制。

3. dgram单播的使用

import dgram from 'dgram';
// 创建指定 type 的 dgram.Socket 对象。type:udp4\udp6
const udpServer = dgram.createSocket('udp4');

/*****************dgram.Socket 事件***********************************/ 

// 在使用 close() 关闭套接字后会触发 'close' 事件。
udpServer.on('close', () => {
  console.log('server is closed')
})
// 在套接字关联到远程地址作为成功的 connect() 调用的结果之后触发
udpServer.on('connect', () => {
  console.log('有connect')
})
// 每当发生任何错误时都会触发 'error' 事件。
udpServer.on('error', (err) => {
  console.log(err)
})
udpServer.on('message', (msg,rinfo) => {
  console.log(`receive message from ${rinfo.address}:${rinfo.port}`);
  console.log(msg)
})
// 一旦 dgram.Socket 可寻址并且可以接收数据,则会触发 'listening' 事件。
udpServer.on('listening', () => {
  console.log('socked 正在监听中')
})

/*******************dgram.Socket 方法******************************/
// 绑定服务端口
udpServer.bind(8866)
// 返回包含套接字地址信息的对象。
const address = udpServer.address();
// 套接字接收缓冲区大小
const recvBufferSize = udpServer.getRecvBufferSize();
// 套接字发送缓冲区大小
const sendBufferSize = udpServer.getSendBufferSize();
// 
udpServer.send('将要发送的消息', 41235, 'localhost', (err) => {
  if (err) return;
  console.log('消息已发送')
})
// 关闭底层套接字并停止监听其上的数据。
udpServer.close()

4. dgram广播

实现广播的前提,我们首先要知道广播地址,广播地址的计算:

  1. 获取本地ip地址
  2. 获取子网掩码
  3. ip地址和子网掩码做运算
  4. 地址中主机位都为1就是广播地址
udpServer.on('listening', () => {
  // 开启广播
  udpServer.setBroadcast(true);
  // 发送指定广播地址
  udpServer.send('各位注意,这是广播消息', 88124, '1.1.1.255')
})
  1. dgram组播 组播地址是实现组播的关键,首先我们要了解组播地址。

IANA将D类地址(224.0.0.0-239.255.255.255)分配给IP组播,用来标识一个IP组播组,由IGMP(组管理协议)协议维护组成员关系:

  • 224.0.0.0~224.0.0.255为永久组地址,地址224.0.0.0保留不做分配,其它地址供路由协议使用
  • 224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet;
  • 224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;
  • 239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。
// 组播
const multicalAddress = '224.10.10.1';
udpServer.on('listening', () => {
  // 添加组播
  udpServer.addMembership(multicalAddress)
  // 发送组播消息
  udpServer.send('各位成员好,这是组内消息', 88124, multicalAddress);
})