UDP简介
- User Datagram Protocol, 简称UDP,又称为用户数据报协议。
- 和TCP一样,位于网路传输层,用于处理数据包。
- UDP最大的特点是无连接
- UDP传输速度快
- UDP数据传输不可靠
- 不提供数据包分组,组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。
- 可靠性由应用层负责
- 支持一对一通信,也支持一对多通信
- 许多关键的互联网应用程序使用UDP
- 如DNS域名系统服务,TFTP简单文件传输协议、DHCP动态主机设置协议等
- UDP适用于对速度要求比较高、对数据质量要求不严谨的应用
- 例如流媒体、实时多人游戏、实时音视频
UDP的三种传播方式
- UDP单播
- 单播是目的地址为单一目标的一种传播方式
- 地址范围: 0.0.0.0 ~ 223.255.255.255
- UDP广播
- 受限广播: 它不被路由转发,IP地址的网络字段为1就是地址 255.255.255.255
- 直接广播: 会被路由转发,IP地址的网络字段定义这个网络,主机字段通常全为1,如192.168.10.255
- UDP组播
- 组播就是把信息传递给一组目的地址
- 地址范围:224.0.0.0~239.255.255.255
- 224.0.0.0~224.0.0.255 为永久组地址,244.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 为本地管理组播,仅在特定本地范围有效。
Node中的dgram模块
Node为我们提供了 dgram模块用于构建UDP服务
使用该模块创建UDP套接字非常简单,UDP套接字一旦创建,即可以作为客户端发送数据,也可以作为服务器接受数据。
UDP单播示例:
const dgram = require('dgram')
const server = dgram.createSocket('udp4')
// 当绑定端口好启动成功后触发
server.on('listening', () => {
const address = server.address()
console.log(`client running ${address.address}: ${address.port}`)
})
// 当收到消息时触发
server.on('message', (msg, remoteInfo) => {
console.log(`来自客户端消息:【${msg}】 from ${remoteInfo.address}: ${remoteInfo.port}`)
server.send('word', remoteInfo.port, remoteInfo.address)
})
// 发生异常触发
server.on('error', err => {
console.log('server error', err)
})
// 绑定端口号
server.bind(20000)
const dgram = require('dgram')
const client = dgram.createSocket('udp4')
// 当绑定端口好启动成功后触发
client.on('listening', () => {
const address = client.address()
console.log(`client running ${address.address}: ${address.port}`)
})
// 发送消息
client.send('hello', 20000, 'localhost')
// 当收到消息时触发
client.on('message', (msg, remoteInfo) => {
console.log(`来自服务端消息:【${msg}】 from ${remoteInfo.address}:${remoteInfo.port}`)
})
// 发生异常触发
client.on('error', err => {
console.log('client error', err)
})
// 绑定端口号
// client.bind(20001)
UDP 广播示例:
发送消息:
const dgram = require('dgram')
const server = dgram.createSocket('udp4')
// 当绑定端口好启动成功后触发
server.on('listening', () => {
const info = server.address()
console.log(`server running ${info.address}: ${info.port}`)
// 开启广播模式
server.setBroadcast(true)
// 案例: 每隔两秒发送一条消息
let a = 1
setInterval(() => {
// 直接地址 可以经过路由转发
// 受限地址 255.255.255.255 不会经过路由转发,只在当前连接的路由器局域网中
server.send(`测试数据${a++}`, 20001, '255.255.255.255')
}, 2000)
})
// 绑定端口号
server.bind(20000)
接收消息:
const dgram = require('dgram')
const client = dgram.createSocket('udp4')
// 当收到消息时触发
client.on('message', (msg, remoteInfo) => {
console.log(`收到消息:【${msg}】 from ${remoteInfo.address}:${remoteInfo.port}`)
})
// 绑定端口号
client.bind(20001)
UDP组播示例
发送数据:
// 组播
const dgram = require('dgram')
const server = dgram.createSocket('udp4')
// 当绑定端口好启动成功后触发
server.on('listening', () => {
const info = server.address()
console.log(`server running ${info.address}: ${info.port}`)
// 案例: 每隔两秒向组播发送一条消息
let a = 1
setInterval(() => {
server.send(`测试数据${a++}`, 20001, '224.1.1.101')
}, 2000)
})
// 绑定端口号
server.bind(20000)
接收数据:
// 组播
const dgram = require('dgram')
const client = dgram.createSocket('udp4')
client.on('listening', () => {
// 加入组播的组
client.addMembership('224.1.1.101')
})
// 当收到消息时触发
client.on('message', (msg, remoteInfo) => {
console.log(`收到消息:【${msg}】 from ${remoteInfo.address}:${remoteInfo.port}`)
})
// 绑定端口号
client.bind(20001)