peiyu1988

前言

UDP是User Datagram Potocol 的简称,它与熟知的TCP协议一样,UDP协议直接位于IP协议的顶层。

UDP适用于一次传输量小,对可靠性要求不高的环境;UDP协议为非连接的协议,没有建立连接的过程,所以它的通信效率极高,但也因此它的可靠性不如TCP。

dgram

dgram 模块提供了UDP数据包socket的实现;

PS:nodejs V10版本内置模块,所以不再需要通过npm下载。

快速开始

const dgram = require('dgram');
const server = dgram.createSocket('udp4');

server.on('error', (err) => {
  console.log(`服务器异常:\n${err.stack}`);
  server.close();
});

server.on('message', (msg, rinfo) => {
  console.log(`服务器收到:${msg} 来自 ${rinfo.address}:${rinfo.port}`);
});

server.on('listening', () => {
  const address = server.address();
  console.log(`服务器监听 ${address.address}:${address.port}`);
});

server.bind(41234);

dgram.createSocket()创建dgram.Socket实例,此实例为包含函数的EventEmitter

close’ 时间将使用close(),关闭socket并且不会在触发新的“message”事件。

'error' 当发生错误时便会触发。

'message' 当接收到新数据时触发,msg和rinfo会被当作参数,传到函数中处理。

  msg:消息 buffer

  rinfo:远程地址信息 (address 发送方地址;family地址类型 IPv4 /IPv6;port发送方端口;size消息大小)

发送信息

socket.send(msg,[offset,length],port,[addr],callback)

  msg:《buffer,string,array》要发送得消息                                            

  offset:指消息开头在buffer中得偏移

  length:消息得字节数

  port:端口号

  addr:接收方得地址

//
const dgram = require('dgram');
const message = Buffer.from('Some bytes');
const client = dgram.createSocket('udp4');
client.send(message, 41234, 'localhost', (err) => {
  client.close();
});

PS:关于UDP包得大小

IPv4/IPv6 数据包得最大尺寸取决于MTU(maximum transmission unit 最大传输单元)与payload length字段大小。

Payload Length字段有16 位宽,指一个超过 64K 的_包含_ IP 头部和数据的负载 (65,507 字节 = 65,535 − 8 字节 UDP 头 − 20 字节 IP 头部);通常对于环回地址来说是这样,但这个长度的数据包对于大多数的主机和网络来说不切实际。

.MTU指的是数据链路层为数据包提供的最大大小。对于任意链路,IPv4所托管的MTU最小为68个字节,推荐为576(典型地,作为拨号上网应用的推荐值),无论它们是完整地还是分块地抵达。

.对于IPv6,MTU的最小值是1280个字节,然而,受托管的最小的碎片重组缓冲大小为1500个字节。现今大多数的数据链路层技术(如以太网),都有1500的MTU最小值,因而68个字节显得非常小。

要提前知道数据包可能经过的每个链路的 MTU 是不可能的。发送大于接受者MTU大小的数据包将不会起作用,因为数据包会被静默地丢失,而不会通知发送者该包未抵达目的地。

进阶函数

socket.getRecvBufferSize()

return number 返回socket接收到得字节大小

socket.getSendBufferSize()

return number 返回socket发送出得字节大小

IPv4/IPv6

//IPv6
//linux 系统
const socket = dgram.createSocket('udp6');

socket.bind(1234, () => {
  socket.setMulticastInterface('::%eth1');
});

//windows 系统
const socket = dgram.createSocket('udp6');

socket.bind(1234, () => {
  socket.setMulticastInterface('::%2');
});

//IPv4
const socket = dgram.createSocket('udp4');

socket.bind(1234, () => {
  socket.setMulticastInterface('10.0.0.2');
});

socket.setMulticastTTL(ttl)/socket.setTTL(ttl)

设置 IP_Multicast_TTL/IP_TTL 套接字选项。一般来说,TTL表示"生存时间",这里特指一个IP数据包传输时允许的最大跳步数。当IP数据包每向前经过一个路由或网关时,TTL值减1,若经过某个路由时,TTL值被减至0,便不再继续向前传输。比较有代表性的是,为了进行网络情况嗅探或者多播而修改TTL值。

传给 socket.setTTL() 的参数是一个范围为0-255的跳步数。大多数系统的默认值是 1 ,但是可以变化。

socket.setRecvBufferSize(size)

设置最大的套接字接收缓冲字节。

socket.setSendBufferSize(size)

设置最大的套接字发送缓冲字节。

贴士 IPv4与IPv6

为何要从IPV4升级到iPV6协议?

IPV4协议支持的物理IP地址已经即将用光,那么不升级协议的话,后面越来越多的联网设备将无法获取到足量的IP地址,也就是连不上网,这个与我们飞速发展的物联网相矛盾的。

IPv4地址长度是32,支持的物理地址是2^32-1个地址;

IPv6地址的长度是128,支持的物理地址是2^128-1个地址。

IPV6相比较IPV4有什么优势?

1、更大的地址空间,IPV6地址容量巨大。

2、iPV6地址分配遵循Aggregation原则,路由器的路由表长度减少,提高转发数据包的速度。

我的系统支持IPV6吗?

以我们目前用的win7或win10系统而言,两种协议是同时支持的

ipv4怎么升级过度到IPV6?

目前有三种主流方案,分别是双栈技术(所有的设备上ipv4 ipv6共存)、隧道技术、GRE隧道and手动隧道ipv6 over ipv4,对于普通用户我们完全不用担心,按时更新系统就可以了。

相关文章: