引言
之前我们介绍了使用 Nodejs 的 net
模块基于 Socket 创建 TCP 协议的服务,同时利用浏览器与我们创建的服务进行了连接,今天我们看一下怎么用 Nodejs 创建 UDP 服务。
UDP又称用户数据包协议,与TCP一样同属于网络传输层。UDP与TCP最大的不同是UDP是无连接的。TCP中连接一旦建立,所有的会话都基于连接完成,客户端如果要与另一个TCP服务通信,需要另创建一个套接字socket
来完成连接。
在UDP中,它提供面向事务的简单不可靠信息传输服务,在网络差的情况下存在丢包严重的问题。但是由于它无须连接,资源消耗低,处理快速且灵活,所以常常应用在那种偶尔丢一两个数据包也不会产生重大影响的场景:比如音视频、流媒体服务等。目前DNS服务、HTTP/3都是基于它实现的。
创建一个 UDP 通信
创建 UDP 套接字
你可以通过 dgram
模块提供的方法来创建UDP套接字:
const datagram = require("dgram"); const socket = datagram.createSocket("udp4");
? UDP套接字一旦创建,既可以作为客户端发送数据,也可以作为服务器端接收数据。
绑定端口
若想让UDP套接字接收网络消息,只要调用 dgram.bind(port, [address])
方法对网卡和端口进行绑定即可:
const datagram = require("dgram"); const socket = datagram.createSocket("udp4"); socket.on('message', (msg, rinfo) => { console.log(`server got message: ${msg} from ${rinfo.address}:${rinfo.port}`); // 3s后关闭此连接 setTimeout(() => { socket.close(); }, 3000) }); socket.on('listening', () => { const address = socket.address(); console.log("server listening:", address.address + ":" + address.port); }); socket.on('close', () => { console.log('closed server!'); }) socket.bind(41234);
? 该套接字将接收所有网卡上41234端口上的消息。在绑定完成后,将触发listening事件。
创建服务端
现在让我们创建一个服务端来与刚才的服务进行通信:
const dgram = require("dgram"); const client = dgram.createSocket("udp4"); // 创建 Buffer 流 const message = new Buffer.from("你好,upd服务端!"); client.send(message, 0, message.length, 41234, '127.0.0.1', (err, bytes) => { client.close(); });
? socket.send(buf, offset, length, port, address, [callback])
可以将客户端信息发送到目标地址。这些参数分别为要发送的Buffer、Buffer的偏移、Buffer的长度、目标端口、目标地址、发送完成后的回调。
与TCP套接字的write()相比,send()方法的参数列表相对复杂,但是它更灵活的地方在于可以随意发送数据到网络中的服务器端,而TCP如果要发送数据给另一个服务器端,则需要重新通过套接字构造新的连接。
最终运行效果:
UDP 套接字事件
UDP套接字相对TCP套接字使用起来更简单,它只是一个 EventEmitter
的实例,而非 Stream
的实例。它具备如下自定义事件:
message
:当UDP套接字侦听网卡端口后,接收到消息时触发该事件,触发携带的数据为消息Buffer对象和一个远程地址信息。listening
:当UDP套接字开始侦听时触发该事件。close
:调用close()方法时触发该事件,并不再触发message事件。error
:当异常发生时触发该事件,如果不侦听,异常将直接抛出,使进程退出。