UDN-企业互联网技术人气社区

板块导航

浏览  : 486
回复  : 2

[Nodejs] Node.js:dgram模块实现UDP通信

[复制链接]
葡萄柚的头像 楼主
发表于 2017-1-5 15:27:58 | 显示全部楼层 |阅读模式
  1、什么是UDP?

  这里简单介绍下,UDP,即用户数据报协议,一种面向无连接的传输层协议,提供不可靠的消息传送服务。UDP协议使用端口号为不同的应用保留其各自的数据传输通道,这一点非常重要。与TCP相比,占用资源更少,传输速度更快。

  2、了解UDP单播、广播和组播

  单播:向一个单播地址发送UDP数据报时,数据报只能被指定的IP主机接收,同一子网下的其它主机都不会接收该数据报。单播过程(假设子网地址:192.168.10,该子网下有两台主机:192.168.10.2,192.168.10.3,向192.168.10.2发送数据报)

  向主机192.168.10.2的8060端口发送数据报,该IP数据报目标IP在以太网中被ARP解析成MAC地址,然后将此MAC地址设置为目标地址发出去。

  该子网下的主机以太网接口看到该数据帧时,对比自己的MAC地址,如果不一样,则忽略该数据帧。

  直到192.168.10.2主机看到该数据帧时,发现MAC一致,则读入该数据帧,然后在IP层对比目标IP和本机IP,在UDP层对比端口号是否一致,最后接收该数据帧。

  广播:向一个广播地址发送UDP数据报,该广播网络下的所有主机都会受到影响,主机根据端口号来判断是否丢弃该数据。广播过程(假设子网地址:192.168.10,则该网络的广播地址为:192.168.10.255,该子网下有两台主机:192.168.10.2,192.168.10.3,向192.168.10.255发送数据报):

  向192.168.10.255主机端口为8060发送数据报,,该IP数据报目标IP在以太网中被ARP解析成MAC地址,然后将此MAC地址设置为目标地址发出去。

  192.168.10.2和192.168.10.3的主机接口都会和此广播地址匹配成功,直到该数据报进入传输层时根据端口是否匹配判断是否丢弃该数据,端口为8060的会保留该数据,否则将数据丢弃。

  广播:向一个组播地址发送UDP数据报,该组网络下的所有主机都会受到影响,主机根据端口号来判断是否丢弃该数据。组播过程原理与广播类似。

   dgram 模块API介绍

  该模块用来创建UDP数据报socket,继承了EventEmitter,该模块的API如下所示:
1.png

  3、UDP单播实现

  单播的原理上面已经说了,这里便不再叙述。

  服务端:
  1. const dgram = require('dgram');
  2. const server = dgram.createSocket('udp4');

  3. server.on('close',()=>{
  4.     console.log('socket已关闭');
  5. });

  6. server.on('error',(err)=>{
  7.     console.log(err);
  8. });

  9. server.on('listening',()=>{
  10.     console.log('socket正在监听中...');
  11. });

  12. server.on('message',(msg,rinfo)=>{
  13.     console.log(`receive message from ${rinfo.address}:${rinfo.port}`);
  14.     server.send('exit',rinfo.port,rinfo.address)
  15. });

  16. server.bind('8060');
复制代码

  客户端:
  1. const dgram = require('dgram');
  2. const client = dgram.createSocket('udp4');

  3. client.on('close',()=>{
  4.     console.log('socket已关闭');
  5. });

  6. client.on('error',(err)=>{
  7.     console.log(err);
  8. });
  9. client.on('message',(msg,rinfo)=>{
  10.     if(msg=='exit') client.close();
  11.     console.log(`receive message from ${rinfo.address}:${rinfo.port}`);
  12. });
  13. client.send(`hello`,8060,'1.1.1.69');
复制代码

  3、UDP广播实现

  要实现UDP广播,就必须知道广播地址,广播地址如何计算呢?可以利用 ipconfig(windows) 或 ifconfig(*unix) 得到ip地址和mask掩码地址,然后利用ip地址与mask子网掩码做与操作得到网络地址,网络地址中主机位都为1就是广播地址,举个例子:
  1. IP:149.88.160.58
  2. mask:11111111.11111111.11000000.00000000
  3. IP&MASK得到网络地址:149.88.128.0/18
  4. 网络号就是主机位全为0,即149.88.10000000.00000000 即149.88.128.0
  5. 广播地址就是主机位全为1,即149.88.10111111.11111111即149.88.191.255
复制代码

  接着实现UDP广播,我机子的IP为1.1.1.69,掩码为255.255.255.0,因此广播地址为1.1.1.255,服务端向广播地址的8061端口发送数据报,客户端绑定本机的8061端口,如下所示:

  服务端:
  1. const dgram = require('dgram');
  2. const server = dgram.createSocket('udp4');

  3. server.on('close',()=>{
  4.     console.log('socket已关闭');
  5. });

  6. server.on('error',(err)=>{
  7.     console.log(err);
  8. });

  9. server.on('listening',()=>{
  10.     console.log('socket正在监听中...');
  11.     server.setBroadcast(!0);//开启广播
  12.     server.setTTL(128);
  13.     server.send('大家好啊,我是服务端.',8061,'1.1.1.255');
  14. });

  15. server.on('message',(msg,rinfo)=>{
  16.     console.log(`receive message from ${rinfo.address}:${rinfo.port}`);
  17. });

  18. server.bind('8060','1.1.1.69');
复制代码

  客户端:
  1. const dgram = require('dgram');
  2. const client = dgram.createSocket('udp4');

  3. client.on('close',()=>{
  4.     console.log('socket已关闭');
  5. });

  6. client.on('error',(err)=>{
  7.     console.log(err);
  8. });
  9. client.on('listening',()=>{
  10.     console.log('socket正在监听中...');
  11. });
  12. client.on('message',(msg,rinfo)=>{
  13.     console.log(`receive message from ${rinfo.address}:${rinfo.port}:${msg}`);
  14. });
  15. client.bind(8061,'1.1.1.69');
复制代码

  3、UDP组播实现

  组播地址是实现UDP组播的关键,因此了解组播地址是重点。什么是组播地址?IANA将D类地址(224.0.0.0-239.255.255.255)分配给IP组播,用来标识一个IP组播组,由IGMP(组管理协议)协议维护组成员关系,其中:

  224.0.0.0~224.0.0.255为永久组地址,地址224.0.0.0保留不做分配,其它地址供路由协议使用;

  224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet;

  224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;

  239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。

  向组播地址发送数据报,只有该组成员才会接收此数据报。

  dgram模块的 addMembership() 方法将socket加入组播组中, dropMembership() 方法退出组播组。下面以组播地址224.100.100.100来实现UDP组播,如下所示:

  服务端:
  1. const dgram = require('dgram');
  2. const server = dgram.createSocket('udp4');
  3. const multicastAddr = '224.100.100.100';

  4. server.on('close',()=>{
  5.     console.log('socket已关闭');
  6. });

  7. server.on('error',(err)=>{
  8.     console.log(err);
  9. });

  10. server.on('listening',()=>{
  11.     console.log('socket正在监听中...');
  12.     server.addMembership(multicastAddr);
  13.     server.setMulticastTTL(128);
  14.     setInterval(()=>{
  15.         sendMsg();
  16.     },1500);
  17. });

  18. server.on('message',(msg,rinfo)=>{
  19.     console.log(`receive message from ${rinfo.address}:${rinfo.port}`);
  20. });

  21. function sendMsg(){
  22.     server.send('大家好啊,我是服务端.',8061,multicastAddr);
  23. }

  24. server.bind('8060','1.1.1.69');
复制代码

  客户端:
  1. const dgram = require('dgram');
  2. const client = dgram.createSocket('udp4');
  3. const multicastAddr = '224.100.100.100';

  4. client.on('close',()=>{
  5.     console.log('socket已关闭');
  6. });

  7. client.on('error',(err)=>{
  8.     console.log(err);
  9. });
  10. client.on('listening',()=>{
  11.     console.log('socket正在监听中...');
  12.     client.addMembership(multicastAddr);
  13. });
  14. client.on('message',(msg,rinfo)=>{
  15.     console.log(`receive message from ${rinfo.address}:${rinfo.port}:${msg}`);
  16. });
  17. client.bind(8061,'1.1.1.69');
复制代码

相关帖子

发表于 2017-1-5 15:28:28 | 显示全部楼层
不错的帖子,支持下
使用道具 举报

回复

发表于 2017-1-5 15:57:56 来自手机 | 显示全部楼层
Very Good!
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部