使用用户数据报
TCP是一个面相连接的协议,它能提供可靠有序的数据流。然而,用户数据报协议(User Datagram Protocol,UDP)是一种无连接的协议,不具备TCP的传输特性。当发送UFP数据包的时候,无法保证数据包都顺序到达,甚至无法保证它能够到达。
虽然有这些缺点,但是它还是非常有用,例如在需要广播消息的时候,并不需要严格地传输保证,或者消息顺序,此外,UDP也可用于不知道网络节点地址的场合。
1. 理解用户数据报
与TCP一样,UDP也位于传输层,在IP层之上,它允许你向其他主机发送消息,而不需要事先的通信来建立必要的传输信道或者数据路径。
与TCP不一样的,UDP不是面相连接的,没有那么高的稳定性,相反,它提供的是一种不可靠的服务。UDP假定错误检测要不没有必要,要不将错误检测放在应用层进行。
2. 理解用户数据报的使用
时间敏感应用程序通常使用UDP,因为此时丢失数据报比等待延时的数据报更合适。
UDP的无状态特性对于服务器响应来自大量的客户端的小查询同样有效,与TCP不同,UDP支持数据包的广播和多播(将数据包发送给所有订阅者)
3. 构建数据报服务器
Node使dgram
模块来支持数据报。
const dgram = require('dgram');
const server = dgram.createSocket('udp4');
dgram.createSocket函数接收套接字类型作为第一个参数,该参数是udp4(IPv4上的UDP),或udp6(IPv6上的UDP)
注意
UDP中不存在真正的服务器,他只是在套接字上监听消息的终端,此处为了便于阐述和理解。
监听消息
UDP服务器接收到消息会发射message
事件,可以绑定到一个端口去接收:
const dgram = require('dgram');
const port = 1234;
const server = dgram.createSocket('udp4');
server.on('listening', () => {
const address = peer.address();
console.log("ADDRESS " + address.address + ":" + address.port);
})
server.bind(port);
查看附加的消息信息
除了发送消息本身之外,message事件还会把一些发送端的基本信息传入回调函数,作为第二个参数:
server.on('message', (data, info) => {
console.log(info.address);
console.log(info.port);
})
4. 创建简单的数据报回送服务器
接收到了消息,并且通过info可以获得源地址,那么你可以回一个消息
等待消息
等待消息就是监听message事件
回消息
server.on('message', (data,info) => {
server.send(message,
0,
message.length,
info.port,
info.address)
})
使用send方法发送消息,它有很多参数:
- 前三个参数对消息进行描述,第一个是缓冲区,第二个是消息的初始偏移位,最后是字节长度。
- 后面两个是目的地的端口和地址。
5. 构建数据报客户端
创建客户端
只需要创建一个UDP套接字,就可以使用它作为客户端发送消息:
const dgram = require('dgram');
// 创建UDP套接字
const client = dgram.createSocket('udp4');
从上面可以看出,除了没有绑定端口,其余部分和创建服务器一样,使用的接口也是dgram.createSocket()
。因为没有绑定特定的端口,消息会从一个随机的UDP端口发出。如果从特定端口发送,需要使用client.bind()
方法。
发送消息
// 创建一个缓冲区
const msg = new Buffer('This is a message');
// 发送消息
const port = 1234;
const host = "localhost";
client.send(message,0,message.length,port,host);
关闭套接字
在上面发送消息的例子中,套接字会在消息被全部传送到网络中后被关闭,但是send()
还可以接受一个回调函数,可以在回调函数中使用close()
手动关闭套接字:
client.send(message,0,message.length,1234,'localhost', (err, bytes) => {
if(err) client.close();
})
回调接受两个参数,一个是错误,一个是发送的字节数。