当前位置: 首页 > 后端技术 > Node.js

Nodejs开发入门—UDP编程,小白轻松学会

时间:2023-04-03 11:03:41 Node.js

UDP协议UDP协议(无连接传输协议)运行在传输层,可以提供一个调用它的应用程序,无需建立连接。一种直接发送数据包的网络传输协议;它主要有以下两个特点:无连接:与TCP需要三次握手建立连接才能传输数据不同,UDP无需任何准备就可以进行数据传输操作,因此UDP不会因连接而导致数据传输延迟;TCP需要维护客户端和服务器的连接状态,才能实现TCP可靠的数据传输服务,而UDP由于是无连接的,所以UDP不需要维护客户端和服务器的连接状态。服务器之间的连接状态。应用层有绝对的控制权:UDP会将应用层的数据包直接交给网络层。同样,接收到网络层的数据包后,会直接交给应用层。UDP不会对数据包进行任何操作;TCP一般使用拥塞控制来防止过多的数据进入网络,造成网络拥塞,而UDP则忽略了这些问题,因此可以最大化网络带宽。由于以上两个原因,使用UDP的应用程序对数据包和带宽有绝对的控制权。但是需要注意的是,即使UDP也使用了检查机制,并不代表它就保证了数据的有效性。UDP检测仅用于检查数据包是否有错误。数据包交给应用层,除了给应用层一些友好的警告,不会采取或提供任何补救措施。与TCP相比,UDP是一种相对简单的传输层网络传输协议。由于其简单性,与TCP相比具有无可比拟的效率优势。因此对DNS、语音、视频流等的效率和准确性要求较高,要求较低的应用一般采用UDP协议。UDP广播(多播)我们常见的UDP服务是一对一的单播服务。接下来我们将讨论一对多的UDP服务:广播:广播和单播的主要区别在于目标IP地址。广播的目标IP地址是一个特定的主机地址,广播的目标IP地址是本地子网中的广播地址,即本地子网下的所有主机都能收到一份数据;多播:也称为多播,它是网络中属于同一服务类型的主机的逻辑分组。信息的发送和接收只发生在同一个组内,不在组内的主机不能发送和接收相应的数据。由于广播会占用局域网内几乎所有的带宽,只能在局域网内使用,所以基于广播的应用与组播相比数量非常少,而组播的一些优点使其非常适用于生产网络生产者/消费者模式下的应用:同组下的主机共享同一个通道,大大节省了服务器的带宽;由于组播协议是由数据消费者决定转发数据的,所以对于生产者的服务器来说,无论作为消费者的客户端有多少,所需的带宽都是固定的;组播不仅可以用于局域网,也可以用于广域网。最后需要说明的是,无论是广播还是组播,它们只是转发数据,并不关心也不能保证接收端能正确收到数据,其特性完全符合UDP协议,所以广播和组播都是常用于UDP协议。应用首先安装dgram模块服务器项代码如下:/***UDP服务器*///加载udp模块constdgram=require("dgram");//创建服务器constserver=dgram.createSocket("udp4");server.on("message",(msg,rinfo)=>{//将收到的消息返回给客户端varstrmsg="您好,UDP客户端,消息已收到!";server.send(strmsg,rinfo.port,rinfo.address);console.log("服务器从"+rinfo.address+":"+rinfo.port+":"+msg.toString());});服务器。on("listening",()=>{letaddress=server.address();console.log("Serverlistening:",adress.adress+":"+adress.port);});server.on("error",(err)=>{console.err("服务器异常错误:"+err.message);});server.bind(8234,"127.0.0.1");客户端项代码如下:/***UDPclient*/constdgram=require("dgram");constclient=dgram.createSocket("udp4");client.on("message",(msg,rinfo)=>{console.log("从以下位置接收消息:"+rinfo.address+":"+rinfo.port+":"+msg.toString());});client.on("error",(err)=>{console.error("客户端错误:"+err.message);});client.on("close",()=>{console.log("socketisclosed");});client.send("我是UDP客户端!",8234,"127.0.0.1",(err)=>{if(err)client.close();});运行结果如下:[Server][Client]上面的例子实现了一个简单的UDP服务,主要涉及dgram.createSocket和dgram.Socket的使用。下面我们一一介绍dgram.createSocketdgram.createSocket主要用于创建dgram.Socket实例;有两个签名:dgram.createSocket(type[,callback]):type:套接字类型,可用值有udp4,udp6;其中udp4是指运行在IPv4下,udp6是指运行在IPv6下;callback:该回调会被加入到dgram.Socket的消息事件监听队列中,当接收到对端发送的数据时触发。dgram.createSocket(options[,callback]):options:属性设置,相关属性如下:type:Socket类型,可用值为udp4和udp6;其中udp4表示在IPv4下运行,udp6表示在IPv6下运行;reuseAddr:ifOnesocketboundto0.0.0.0:41234,andanothersocketboundto127.0.0.1:41234:如果reuseAddr为false,会抛出EADDRINUSE异常,因为0.0.0.0代表任意IP地址,其他IP地址(如上面的127.0.0.1)会被系统占用;如果reuseAddr为true,那么0.0.0.0:41234和127.0.0.1:41234代表完全不同的地址端口对,所以两个socket都可以绑定成功。此属性的默认值为false。ipv6Only:是否关闭双协议栈;默认值为假;recvBufferSize:设置socketSO_RCVBUF的值,即设置接收缓冲区的大小;sendBufferSize:设置socketSO_SNDBUF的值,即设置发送缓冲区的大小;lookup:自动定义DNS查询逻辑,默认调用dns.lookup();signal:使用指定的AbortSignal关闭套接字。callback:该回调会被加入到dgram.Socket的消息事件监听队列中,当接收到对端发送的数据时触发。dgram.Socketdgram.Socket主要用作服务端和客户端之间的通信桥梁。常用方法bind:绑定IP地址和端口号,使通信的另一端可以通过指定的IP地址和端口号向套接字发送数据报信息。该方法有如下两个签名:socket.bind(port[,callback]):port:要绑定的端口号,如果该参数值为0或不指定,系统将随机分配端口号;address:要绑定的IP地址,默认值为0.0.0.0;callback:绑定完成后的回调函数。socket.bind(options[,callback]):options:属性设置,相关属性如下:port:要绑定的端口号,如果该参数值为0或不指定,系统会随机分配段号;address:要绑定的IP地址,默认值为0.0.0.0;exclusive:是否允许集群中的共享服务监听句柄;默认值为假;fd:现有的socket相关的文件描述符,如果指定则使用socket,否则会创建一个新的socket。callback:绑定完成后的回调函数。close:关闭socket并停止监听来自通信另一端的数据报,该方法会触发close事件;connect:与通信另一端的地址和端口号建立关联,相关参数如下:port:通信另一端的端口号;address:通信另一端的地址,udp4下默认为127.0.0.1,udp6下为::1;callback:连接成功后,会触发connect事件和指定的回调。如果连接失败,只会触发指定的回调。前面我们说过UDP是无连接协议,所以这里的connect并不是要在通信双方之间建立真正的连接,而只是设置通信另一端的地址和端口号;连接建立后,socket.send()调用不需要指定端口和地址参数,只会接收来自连接指定的通信另一端的数据报。disconnect:断开通信另一端的地址和端口号;send:发送数据报给指定的通信另一端,相关参数如下:msg:要发送的数据报;offset:数据报的第一个字节在缓冲区中length:数据报的字节大小;port:通讯另一端的端口号,如果当前socket未连接,则需要指定该参数,否则不指定该参数将使用连接时指定的端口号;address:通信另一端的地址,如果当前socket没有连接,则需要指定该参数,否则使用连接时指定的地址,不指定该参数;callback:数据报发送成功后的回调函数。setBroadcast:设置socket选项SO_BROADCAST的值,控制是否允许发送广播数据,参数flag为boolean类型;setMulticastInterface:设置组播接口,参数multicastInterface为字符串类型;在IPv4和IPv6中它的取值如下:在IPv4下,取值为具体的IP地址,例如下面的例子:constsocket=dgram.createSocket('udp4');socket.bind(1234,()=>{socket.setMulticastInterface('10.0.0.2');});复制代码在IPv6下,该值应该包含一个范围,例如下面的例子:constsocket=dgram.createSocket('udp6');socket.bind(1234,()=>{socket.setMulticastInterface('::%eth1');});复制代码addMembership:将指定地址加入到指定接口上无限源的多播组中(内部使用socket选项IP_ADD_MEMBERSHIP),相关参数如下:multicastAddress:多播地址;multicastInterface:多播接口,如果不指定,操作系统会自行选择一个接口。dropMembership:从指定接口上的无限源组播组中移除指定地址(内部使用套接字选项IP_DROP_MEMBERSHIP),相关参数如下:multicastAddress:组播地址;multicastInterface:多播接口,如不指定,指定的地址将从第一个匹配的多播组中移除。addSourceSpecificMembership:在指定接口上添加源特定组播组(内部使用套接字选项IP_ADD_SOURCE_MEMBERSHIP),相关参数如下:sourceAddress:源地址;groupAddress:组播组地址;multicastInterface:多播接口,如不指定,操作系统会自行选择一个接口。dropSourceSpecificMembership:移除指定接口上的特定源组播组(内部使用套接字选项IP_DROP_SOURCE_MEMBERSHIP),相关参数如下:sourceAddress:源地址;groupAddress:组播组地址;multicastInterface:多播接口,如未指定,第一个匹配的特定源多播组之间的成员资格将被打破。setMulticastLoopback:设置socket选项IP_MULTICAST_LOOP的值,控制数据是否可以环回本地环回接口(默认情况下,当本机向网络接口发送多播数据时,在IP层,数据会环回toLocalloopbackinterface),其参数flag为boolean类型。相关事件监听:当socket准备好接收数据时触发;该事件可以通过socket.bind()显式触发,也可以通过socket.send()隐式触发;需要注意的是,在该事件触发之前,socket相关的系统资源将不可用;connect:调用socket.connect()与对端建立连接成功后触发;message:套接字收到新数据报时触发;回调函数的参数如下:msg:数据报信息,类型为Buffer;rinfo:数据报发送者信息,相关属性如下:address:数据报发送者IP地址;family:数据报发送方IP地址协议版本,取值为IPv4或IPv6;port:数据报发送方的端口号;大小:数据报的大小。error:发生异常时触发;close:调用socket.close()成功关闭socket后触发;该事件一旦触发,消息事件将不再触发。总结在本文中,我们首先介绍UDP协议,它是一种无连接、不可靠的传输层传输协议。该协议常用于DNS、NFS、多媒体流等领域;在了解了相关协议的基本运行原理之后,我们接着介绍了Node.js中dgram模块的使用;我们希望通过这种从原理到实践的方式,让大家真正掌握Node.js网络编程。源码附件已经打包上传到百度云,大家可以自行下载~链接:https://pan.baidu.com/s/14G-b...提取码:yu27百度云链接不稳定,随时可能坏掉无效,请抓紧保存。百度云链接失效请留言告诉我,我看到后会及时更新~GIT项目推荐:含多终端免license商业附件地址:https://gitee.com/ZhongBangKeJi