NODEJS UDP通信

nodejs组播通信

最近想学习一下nodejs传输层通信的内容,在网上找了一些资料自己学习着做了一下
[AY-Node.js]写给自己的NodeJs-通讯系统-udp-dgram模块
Node.js:dgram模块实现UDP通信
Node.js Manual & Documentation
nodejs可以支持TCP/UDP的通信,其中tcp可以通过net模块实现,udp通过dgram模块实现。这里主要想试试组播通信,就先试试dgram的UDP通信。

UDP组播

在tcp/ip协议簇中IANA规定了D类ip地址分配给组播,具体就是224.0.0.0-239.255.255.255。每个ip可以标记一个组播组,由IGMP协议维护。组播ip地址具体又有几种细分:

224.0.0.0224.0.0.255//永久组地址,地址224.0.0.0保留不做分配,其它地址供路由协议使用;
224.0.1.0224.0.1.255//公用组播地址,可以用于Internet;
224.0.2.0238.255.255.255//用户可用的组播地址(临时组地址),全网范围内有效;
239.0.0.0239.255.255.255//本地管理组播地址,仅在特定的本地范围内有效。

通过dgram模块中addMembership()方法将socket加入组播组中,dropMembership()方法退出组播组。只有加入组播组才能接收到组播数据。

实现

//代码是参考的Node.js:dgram模块实现UDP通信

服务端代码:


/*server*/
const dgram = require('dgram'); 
const server = dgram.createSocket('udp4'); //创建udp服务器
const multicastAddr = '224.100.100.100';

//以下server.on 都是在监听不同信号
server.on('close',()=>{ // ()=> 是 ES6的箭头函数,写成 function()也是可以的
    console.log('socket已关闭');
});

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

server.on('listening',()=>{
    console.log('socket正在监听中...');
    server.addMembership(multicastAddr); //加入组播组
    server.setMulticastTTL(128);

});

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

function sendMsg(){
    var message = '大家好啊,我是服务端.';
    server.send(message,0,message.length,8061,multicastAddr);
    //通过server.send发送组播
    //参数分别是,数据(buffer或者string),偏移量(即开始发送的位子),数据长度,接收的端口,组播组
}

server.bind(8060); //绑定端口,不绑定的话也可以send数据但是无法接受

//循环发送
setInterval(()=>{
    sendMsg();
    console.log("send message");
},1500);

客户端代码:

/*client*/
//基本与服务端类似
const dgram = require('dgram');
const client = dgram.createSocket('udp4');
const multicastAddr = '224.100.100.100';

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

client.on('error',(err)=>{
    console.log(err);
});
client.on('listening',()=>{
    console.log('socket正在监听中...');
    client.addMembership(multicastAddr);
});
client.on('message',(msg,rinfo)=>{
    console.log(`receive message from ${rinfo.address}:${rinfo.port}:${msg}`);
});
client.bind(8061);

遇到的问题

同一台主机上服务器与客户端可以通信,但不同主机间不能通信,wireshark抓不到数据包。

猜测可能是主机上局域网太多,服务器选择了不同的网卡,导致不在一个网段内。抓取了数据包源IP,证实了使用的是另一个虚拟网段。禁用其他网段的网卡后问题解决。

UDP广播

广播地址

广播地址比组播简单,IP协议中将主机号全为1的地址留给了广播。利用主机号和子网掩码可以算出当前网段的广播地址。

IP地址:10.108.92.2
子网掩码:255.255.252.0
子网掩码后十位为零 -> 即主机号为后十位 -> 将IP地址的后十位置一 -> 得到广播地址10.108.95.255

最后代码如下,通过上面组播的客户端和服务器端代码也可以看得很清楚了,其实UDP通信中并不建立连接,不用过度区分服务端和客户端。发送数据的就是服务端,接收的就是客户端

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

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

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

server.on('listening',()=>{
    console.log('socket正在监听中...');
    server.setBroadcast(true);//开启广播
    server.setTTL(128);//路由一跳TTL减一,减到零抛弃数据包
    server.send('大家好啊,我是服务端.',8061,'10.108.95.255');
    //在send {msg=close} 可以发送 colse 事件
});
//通过message事件接收数据,
server.on('message',(msg,rinfo)=>{
    console.log(`receive message from ${rinfo.address}:${rinfo.port}`);
});
//绑定,要接收数据的话必须绑定
server.bind('8060','10.108.92.2');

猜你喜欢

转载自blog.csdn.net/lucifly/article/details/60573225