Node.js API詳解之 dgram模塊用法實例分析
本文實例講述了Node.js API詳解之 dgram模塊用法。分享給大家供大家參考,具體如下:
Node.js API詳解之 dgram
dgram模塊提供了 UDP 數據包 socket 的實現。
使用以下方式引用:
const dgram = require('dgram');
dgram.createSocket(options[, callback])
說明:
創(chuàng)建一個 dgram.Socket 對象. 一旦創(chuàng)建了套接字,調用 socket.bind() 會指示套接字開始監(jiān)聽數據報消息。
如果 address 和 port 沒傳給 socket.bind(),
那么這個方法會把這個套接字綁定到 “全部接口” 地址的一個隨機端口(這適用于 udp4 和 udp6 套接字)。
綁定的地址和端口可以通過 socket.address().address 和socket.address().port 來獲取
options:
type:套接字族. 必須是 ‘udp4' 或 ‘udp6'. 必需填.
reuseAddr:若設置為 true socket.bind() ,則會 重用地址,即時另一個進程已經在其上面綁定了一個套接字。 默認是 false.
recvBufferSize: 設置 SO_RCVBUF 套接字值。
sendBufferSize: 設置 SO_SNDBUF 套接字值。
lookup:慣常的查詢函數. 默認是 dns.lookup()。
callback:為 ‘message' 事件綁定一個監(jiān)聽器??蛇x。
demo:
const dgram = require('dgram'); const server = dgram.createSocket({type: 'udp4'}, () => { console.log(`服務器收到:${msg} 來自 ${rinfo.address}:${rinfo.port}`); }); server.bind(41234); // 服務器監(jiān)聽 0.0.0.0:41234
dgram.createSocket(type[, callback])
說明:
創(chuàng)建一個特定 type 的dgram.Socket 對象。type參數是udp4 或 udp6。
可選傳一個回調函數,作為 ‘message' 事件的監(jiān)聽器。
demo:
const dgram = require('dgram'); const server = dgram.createSocket('udp4', () => { console.log(`服務器收到:${msg} 來自 ${rinfo.address}:${rinfo.port}`); }); server.bind(41234);
dgram.Socket 類
說明:
dgram.Socket對象是一個封裝了數據包函數功能的EventEmitter。
dgram.Socket實例是由dgram.createSocket()創(chuàng)建的。
創(chuàng)建dgram.Socket實例不需要使用new關鍵字。
socket.bind([port][, address][, callback])
說明:
對于 UDP socket,該方法會令dgram.Socket在指定的port和可選的address上監(jiān)聽數據包信息。
若port未指定或為 0,操作系統會嘗試綁定一個隨機的端口。
若address未指定,操作系統會嘗試在所有地址上監(jiān)聽。
綁定完成時會觸發(fā)一個'listening'事件,并會調用callback方法。
注意,同時監(jiān)聽'listening'事件和在socket.bind()方法中傳入callback參數并不會帶來壞處,但也不是很有用。
一個被綁定的數據包 socket 會令 Node.js 進程保持運行以接收數據包信息。
若綁定失敗,一個'error'事件會被觸發(fā)。在極少數的情況下(例如嘗試綁定一個已關閉的 socket),一個 Error 會被拋出。
demo:
const dgram = require('dgram'); const server = dgram.createSocket('udp4', () => { console.log(`服務器收到:${msg} 來自 ${rinfo.address}:${rinfo.port}`); }); server.bind(41234, () => { const address = server.address(); console.log(`服務器監(jiān)聽 ${address.address}:${address.port}`); }); // 服務器監(jiān)聽 0.0.0.0:41234
socket.bind(options[, callback])
說明:
options:{port:”, address: ”, exclusive: ”}
對于 UDP socket,該方法會令dgram.Socket在指定的port和可選的address上監(jiān)聽數據包信息。
若port未指定或為 0,操作系統會嘗試綁定一個隨機的端口。
若address未指定,操作系統會嘗試在所有地址上監(jiān)聽。
綁定完成時會觸發(fā)一個'listening'事件,并會調用callback方法。
在配合cluster模塊使用dgram.Socket對象時,options對象可能包含一個附加的exclusive屬性。
當exclusive被設為false(默認值)時,集群工作單元會使用相同的 socket 句柄來共享連接處理作業(yè)。
當exclusive被設為true時,該句柄將不會被共享,而嘗試共享端口則會造成錯誤。
一個綁定的數據報 socket 會使 Node.js 進程持續(xù)運行以接受數據報消息。
如果綁定失敗,一個 ‘error' 事件會產生。在極少數情況下(例如嘗試綁定一個已經關閉的 socket), 一個 Error 可能拋出。
demo:
const dgram = require('dgram'); const server = dgram.createSocket('udp4', () => { console.log(`服務器收到:${msg} 來自 ${rinfo.address}:${rinfo.port}`); }); server.bind({port: 41234}, () => { const address = server.address(); console.log(`服務器監(jiān)聽 ${address.address}:${address.port}`); }); // 服務器監(jiān)聽 0.0.0.0:41234
listening 事件
說明:
當一個 socket 開始監(jiān)聽數據包信息時,'listening'事件將被觸發(fā)。
該事件會在創(chuàng)建 UDP socket 之后被立即觸發(fā)。
demo:
const dgram = require('dgram'); const server = dgram.createSocket('udp4', () => { console.log(`服務器收到:${msg} 來自 ${rinfo.address}:${rinfo.port}`); }); server.on('listening', () => { const address = server.address(); console.log(`服務器監(jiān)聽 ${address.address}:${address.port}`); }); server.bind({port: 41234}); // 服務器監(jiān)聽 0.0.0.0:41234
error 事件
說明:
當有任何錯誤發(fā)生時,'error'事件將被觸發(fā)。
事件發(fā)生時,事件處理函數僅會接收到一個 Error 參數。
demo:
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(`服務器監(jiān)聽 ${address.address}:${address.port}`); }); server.bind({port: 41234});
message 事件
說明:
當有新的數據包被 socket 接收時,'message'事件會被觸發(fā)。
msg和rinfo會作為參數傳遞到該事件的處理函數中。
msg:消息
rinfo:遠程地址信息
address:發(fā)送方地址
family: 地址類型 (‘IPv4' or ‘IPv6')
port: 發(fā)送者端口
size: 消息大小
demo:
const dgram = require('dgram'); const server = dgram.createSocket('udp4'); server.on('message', (msg, rinfo) => { console.log(`服務器收到:${msg} 來自 ${rinfo.address}:${rinfo.port}`); }); server.on('listening', () => { const address = server.address(); console.log(`服務器監(jiān)聽 ${address.address}:${address.port}`); }); server.bind({port: 41234});
socket.getRecvBufferSize()
說明:
socket 接收到的字節(jié)大小。
demo:
server.on('message', (msg, rinfo) => { console.log(`服務器收到字節(jié)數:${socket.getRecvBufferSize()}`); });
socket.setRecvBufferSize(size)
說明:
設置 SO_RCVBUF 套接字選項。設置最大的套接字接收緩沖字節(jié)。
demo:
const dgram = require('dgram'); const server = dgram.createSocket('udp4'); server.setRecvBufferSize(1024); server.on('message', (msg, rinfo) => { console.log(`服務器收到字節(jié)數:${socket.getRecvBufferSize()}`); }); server.bind({port: 41234});
socket.send(msg, [offset, length,] port [, address] [, callback])
說明:
在 socket 上發(fā)送一個數據包。目標port和address須被指定。
msg參數包含了要發(fā)送的消息。根據消息的類型可以有不同的做法。
如果msg是一個Buffer 或 Uint8Array,則offset和length指定了消息在Buffer中對應的偏移量和字節(jié)數。
如果msg是一個String,那么它會被自動地按照utf8編碼轉換為Buffer。
對于包含了多字節(jié)字符的消息,offset和length會根據對應的byte length進行計算,而不是根據字符的位置。
如果msg是一個數組,那么offset和length必須都不能被指定。
address參數是一個字符串。若address的值是一個主機名,則 DNS 會被用來解析主機的地址。
若address未提供或是非真值,則'127.0.0.1'(用于 udp4 socket)或'::1'(用于 udp6 socket)會被使用。
若在之前 socket 未通過調用bind方法進行綁定,socket 將會被一個隨機的端口號賦值并綁定到“所有接口”的地址上(對于udp4 socket 是'0.0.0.0',對于udp6 socket 是'::0')。
可以指定一個可選的callback方法來匯報 DNS 錯誤或判斷可以安全地重用buf對象的時機。
注意,在 Node.js 事件循環(huán)中,DNS 查詢會對發(fā)送造成至少 1 tick 的延遲。
確定數據包被發(fā)送的唯一方式就是指定callback。若在callback被指定的情況下有錯誤發(fā)生,該錯誤會作為callback的第一個參數。
若callback未被指定,該錯誤會以'error'事件的方式投射到socket對象上。
偏移量和長度是可選的,但如其中一個被指定則另一個也必須被指定。
另外,他們只在第一個參數是Buffer 或 Uint8Array 的情況下才能被使用。
demo:
const dgram = require('dgram'); const server = dgram.createSocket('udp4'); const buf1 = Buffer.from('Some '); const buf2 = Buffer.from('bytes'); server.on('error', (err) => { console.log(`服務器異常:\n${err.stack}`); server.close(); }); server.on('message', (msg, rinfo) => { console.log(`服務器收到字節(jié)數:${socket.getRecvBufferSize()}`); }); server.on('listening', () => { const address = server.address(); console.log(`服務器監(jiān)聽 ${address.address}:${address.port}`); }); server.send([buf1, buf2], 8080, 'localhost'); server.bind({port: 41234});
socket.getSendBufferSize()
說明:
socket 發(fā)送的字節(jié)大小。
demo:
server.send([buf1, buf2], 8080, 'localhost', () => { console.log('發(fā)送消息字節(jié)數:', server.getSendBufferSize()); });
socket.setSendBufferSize(size)
說明:
設置 SO_SNDBUF 套接字選項。設置最大的套接字發(fā)送緩沖字節(jié)。
demo:
const socket = dgram.createSocket('udp6'); socket.bind(1234, () => { socket.setSendBufferSize(1024); });
socket.unref()
說明:
默認情況下,綁定一個 socket 會在 socket 運行時阻止 Node.js 進程退出。
socket.unref() 方法用于將 socket 從維持 Node.js 進程的引用列表中解除。
可以使用 socket.ref() 再次激活。
socket.unref() 方法返回一個對 socket 的引用,所以可以鏈式調用。
demo:
const dgram = require('dgram'); const socket = dgram.createSocket('udp6'); socket.bind(1234, () => { socket.unref(); });
socket.ref()
說明:
默認情況下,綁定一個 socket 會在 socket 運行時阻止 Node.js 進程退出。
socket.unref() 方法用于將 socket 從維持 Node.js 進程的引用列表中解除。
socket.ref() 方法用于將 socket 重新添加到這個引用列表中,并恢復其默認行為。
多次調用 socket.ref() 不會有額外的作用。
socket.ref() 方法返回一個對 socket 的引用,所以可以鏈式調用。
demo:
const dgram = require('dgram'); const socket = dgram.createSocket('udp6'); socket.bind(1234, () => { socket.unref(); socket.ref() });
socket.close([callback])
說明:
關閉該 socket 并停止監(jiān)聽其上的數據。
如果提供了一個回調函數,它就相當于為'close'事件添加了一個監(jiān)聽器。
demo:
const dgram = require('dgram'); const socket = dgram.createSocket('udp6'); socket.bind(1234); socket.close(() => { console.log('socket 已關閉'); }); // socket 已關閉
close 事件
說明:
‘close'事件將在使用close()關閉一個 socket 之后觸發(fā)。
該事件一旦觸發(fā),這個 socket 上將不會觸發(fā)新的'message'事件。
demo:
const dgram = require('dgram'); const socket = dgram.createSocket('udp6'); socket.bind(1234); socket.on('close', () => { console.log('socket 已關閉'); }) socket.close(); // socket 已關閉
socket.address()
說明:
返回一個包含 socket 地址信息的對象。
對于 UDP socket,該對象將包含address、family和port屬性。
demo:
server.on('listening', () => { const address = server.address(); console.log(`服務器監(jiān)聽 ${address.address}:${address.port}`); });
socket.addMembership(multicastAddress[, multicastInterface])
說明:
通知內核將multicastAddress和multicastInterface提供的多路傳送集合通過IP_ADD_MEMBERSHIP這個 socket 選項結合起來。
若multicastInterface參數未指定,操作系統將會選擇一個接口并向其添加成員。
要為所有可用的接口添加成員,可以在每個接口上調用一次addMembership方法。
socket.dropMembership(multicastAddress[, multicastInterface])
說明:
引導內核通過IP_DROP_MEMBERSHIP這個 socket 選項刪除multicastAddress指定的多路傳送集合。
當 socket 被關閉或進程被終止時,該方法會被內核自動調用,所以大多數的應用都不用自行調用該方法。
若multicastInterface未指定,操作系統會嘗試刪除所有可用接口上的成員。
socket.setBroadcast(flag)
說明:
設置或清除 SO_BROADCAST socket 選項。
當設置為 true, UDP包可能會被發(fā)送到一個本地接口的廣播地址
socket.setMulticastLoopback(flag)
說明:
設置或清除 IP_MULTICAST_LOOP socket 選項。當設置為 true, 多播數據包也將在本地接口接收。
socket.setMulticastTTL(ttl)
說明:
設置IP_MULTICAST_TTL套接字選項。 一般來說,TTL表示”生存時間”。這里特指一個IP數據包傳輸時允許的最大跳步數,尤其是對多播傳輸。
當IP數據包每向前經過一個路由或網關時,TTL值減1,若經過某個路由時,TTL值被減至0,便不再繼續(xù)向前傳輸。
傳給 socket.setMulticastTTL() 的參數是一個范圍為0-255的跳步數。大多數系統的默認值是 1 ,但是可以變化。
socket.setTTL(ttl)
說明:
設置 IP_TTL 套接字選項。 一般來說,TTL表示”生存時間”,這里特指一個IP數據包傳輸時允許的最大跳步數。
當IP數據包每向前經過一個路由或網關時,TTL值減1,若經過某個路由時,TTL值被減至0,便不再繼續(xù)向前傳輸。
比較有代表性的是,為了進行網絡情況嗅探或者多播而修改TTL值。
傳給 socket.setTTL() 的參數是一個范圍為0-255的跳步數。大多數系統的默認值是 1 ,但是可以變化。
希望本文所述對大家node.js程序設計有所幫助。
相關文章
nodejs+socket.io實現p2p消息實時發(fā)送的項目實踐
本文主要介紹了nodejs+socket.io實現p2p消息實時發(fā)送,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-06-06