我们知道,TCP是一种基于连接的协议,在进行通信前,首先要求客户端与服务器端建立一条用于通信的连接。而UDP是一种面向非连接的协议,在进行通信前,不要求首先建立客户端与服务器端的连接,可以直接把数据包发送给对方。基于这个原因,UPD也是一种不可靠的协议,但是其传输速度比TCP更快,因此更适用于实时通信的场合。
在Node.js中,提供了dgram模块,用于创建UPD服务器与客户端,以及实现UDP服务器与客户端之间的通信。
一、 创建UDP服务器与客户端
在dgram模块中,可以使用crateSocket方法创建一个用于实现UDP通信的socket端口对象。
const socket = dgram.createSocket(type, [callback]);
type:用于指定进行UDP通信时使用的协议类型,可指定值为“upd4”或“upd6”。
callback:可选,用于指定当从该端口接收到数据时调用的回调函数。该回调函数使用方法如下:function (msg, rinfo) { }
该回调函数中可以使用两个参数:
msg:参数值为一个Buffer对象,其中存放了接收到的数据。
rinfo:参数值也是一个对象,该对象具有如下属性:
- address:属性值为发送者所使用的地址,如127.0.0.1。
- family:属性值为一个标识了发送者所使用的地址是IPv4地址还是IPv6地址的字符串,例如“IPv4”。
- port:属性值为发送者所使用的socket端口号,例如49436。
- size:属性值为发送者所发送的数据的字节数。
当从socket端口中接收到数据时,触发该socket对象的message事件,可以不在createSocket方法中使用callback参数。
socket.on('message', function(msg, rinfo) {
})
在创建了socket端口对象后,可以使用该socket端口对象的bind方法来指定该socket端口对象所监听的地址与端口号。当创建UDP服务器时,必须使用该方法,这样UDP客户端才能知道向哪个地址发送数据。
socket.bind(port, [address], [callback])
port:参数值为一个整数,用于指定该socket端口对象所监听的端口号。
address:可选,参数值为一个字符串,用于指定该socket端口对象所监听的地址,该地址可以为一个IP地址,也可以为一个主机名。如果不指定address参数,该socket端口对象将监听来自于所有地址的数据。
callback:可选,当指定了bind方法之后,该socket端口对象将立即监听来自于指定地址和端口号的数据,可使用callback参数值指定开始监听时所要调用的回调函数,也可以对socket端口对象的listening事件进行监听,该回调函数不使用任何参数。socket.on('listening', function() { }
当创建了一个socket端口对象之后可以利用该socket端口对象的send方法向外发送数据。
socket.send(buf, offset, length, port, address, [callback])
buf: 代表了一个缓存区的buffer对象,该缓存区中存放了需要发送的数据。
offset:参数值为一个整数,用于指定从缓存区的第几个字节处开始取出要发送的数据。
length:参数值为一个整数,用于指定需要发送的字节数。
prot:参数为一个整数,用于指定接受数据的socket端口对象所使用的端口号。
address:参数值为一个字符串,用于指定接收数据的socket端口对象所属地址。
callback:可选,指定当数据发送完毕时所需调用的回调函数。function(err, bytes) { }
err:发送数据失败时触发的错误对象,在发送数据时产生的失败通常是由于DNS解析错误引起。
bytes:参数值为发送数据的字节数
如果在发送数据前还没有使用该socket端口对象的bind方法来指定其端口号及地址,操作系统将为其分配一个随机端口号并指定其可以接收来自于任何地址的数据。
可以使用socket端口对象的address方法获取该socket端口对象相关的地址信息。
let address = socket.address()
该方法返回一个对象,其中具有如下属性:
- port:属性值为该socket端口对象的端口号。
- address:属性值为该socket端口对象所属地址。
- family:属性值为一个标识了该socket端口对象所属地址是IPv4地址还是IPv6地址的字符串。
创建简单UDP服务器
const dgram = require('dgram');
const server = dgram.createSocket('udp4');
server.on("message", function (msg, rinfo) {
console.log('已接收到客户端发送的数据:' + msg);
console.log("客户端地址信息为:", rinfo);
let buf = new Buffer('确认信息为:' + msg);
server.send(buf, 0, buf.length, rinfo.port, rinfo.address);
});
server.on("listening", function () {
let address = server.address();
console.log("服务器开始监听。地址信息为", address);
});
server.bind(41234, 'localhost');
创建简单UDP客户端
const dgram = require('dgram');
let message = new Buffer('你好。');
const client = dgram.createSocket('udp4');
client.send(message, 0, message.length, 41234, "localhost", function (err, bytes) {
if (err) {
console.log('发送数据失败');
} else {
console.log("已发送字节数据。", bytes);
}
});
client.on('message', function (msg, rinfo) {
console.log('已接收到服务器端发送的数据', msg);
console.log('服务器地址为', rinfo.address);
console.log('服务器所用端口号为', rinfo.port);
});
未完待续。。。。