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數據報,該組網絡下的所有主機都會受到影響,主機根據端口號來判斷是否丟棄該數據。組播過程原理與廣播類似。
3、dgram
模塊API介紹
該模塊用來創建UDP數據報socket,繼承了EventEmitter,該模塊的API如下所示:
3、UDP單播實現
單播的原理上面已經說了,這里便不再敘述。
服務端:
const dgram = require('dgram');
const server = dgram.createSocket('udp4');
server.on('close',()=>{
console.log('socket已關閉');
});
server.on('error',(err)=>{
console.log(err);
});
server.on('listening',()=>{
console.log('socket正在監聽中...');
});
server.on('message',(msg,rinfo)=>{
console.log(`receive message from ${rinfo.address}:${rinfo.port}`);
server.send('exit',rinfo.port,rinfo.address)
});
server.bind('8060');
客戶端:
const dgram = require('dgram');
const client = dgram.createSocket('udp4');
client.on('close',()=>{
console.log('socket已關閉');
});
client.on('error',(err)=>{
console.log(err);
});
client.on('message',(msg,rinfo)=>{
if(msg=='exit') client.close();
console.log(`receive message from ${rinfo.address}:${rinfo.port}`);
});
client.send(`hello`,8060,'1.1.1.69');
3、UDP廣播實現
要實現UDP廣播,就必須知道廣播地址,廣播地址如何計算呢?可以利用ipconfig(windows)
或ifconfig(*unix)
得到ip地址和mask掩碼地址,然后利用ip地址與mask子網掩碼做與操作得到網絡地址,網絡地址中主機位都為1就是廣播地址,舉個例子:
IP:149.88.160.58
mask:11111111.11111111.11000000.00000000
IP&MASK得到網絡地址:149.88.128.0/18
網絡號就是主機位全為0,即149.88.10000000.00000000 即149.88.128.0
廣播地址就是主機位全為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端口,如下所示:
服務端:
const dgram = require('dgram');
const 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(!0);//開啟廣播
server.setTTL(128);
server.send('大家好啊,我是服務端.',8061,'1.1.1.255');
});
server.on('message',(msg,rinfo)=>{
console.log(`receive message from ${rinfo.address}:${rinfo.port}`);
});
server.bind('8060','1.1.1.69');
客戶端:
const dgram = require('dgram');
const client = dgram.createSocket('udp4');
client.on('close',()=>{
console.log('socket已關閉');
});
client.on('error',(err)=>{
console.log(err);
});
client.on('listening',()=>{
console.log('socket正在監聽中...');
});
client.on('message',(msg,rinfo)=>{
console.log(`receive message from ${rinfo.address}:${rinfo.port}:${msg}`);
});
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組播,如下所示:
服務端:
const dgram = require('dgram');
const server = dgram.createSocket('udp4');
const multicastAddr = '224.100.100.100';
server.on('close',()=>{
console.log('socket已關閉');
});
server.on('error',(err)=>{
console.log(err);
});
server.on('listening',()=>{
console.log('socket正在監聽中...');
server.addMembership(multicastAddr);
server.setMulticastTTL(128);
setInterval(()=>{
sendMsg();
},1500);
});
server.on('message',(msg,rinfo)=>{
console.log(`receive message from ${rinfo.address}:${rinfo.port}`);
});
function sendMsg(){
server.send('大家好啊,我是服務端.',8061,multicastAddr);
}
server.bind('8060','1.1.1.69');
客戶端:
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,'1.1.1.69');
另外UDP內網穿透相關的內容,大家也可自行了解一下。