穩(wěn)定性: 3 - 穩(wěn)定
Node.js的dgram模塊提供了UDP數(shù)據(jù)報套接字的實現(xiàn)。
使用數(shù)據(jù)報文sockets(Datagram sockets)的方式是調(diào)用require('dgram')
。
重要提醒:dgram.Socket#bind()
的行為在v0.10做了改動 ,它總是異步的。如果你的代碼像下面的一樣:
var s = dgram.createSocket('udp4');
s.bind(1234);
s.addMembership('224.0.0.114');
現(xiàn)在需要改為:
var s = dgram.createSocket('udp4');
s.bind(1234, function() {
s.addMembership('224.0.0.114');
});
type
字符串。 'udp4'或'udp6'callback
函數(shù)。附加到message
事件的監(jiān)聽器??蛇x參數(shù)。創(chuàng)建指定類型的數(shù)據(jù)報文(datagram) Socket。有效類型是udp4
和udp6
接受一個可選的回調(diào),會被添加為message
的監(jiān)聽事件。
如果你想接收數(shù)據(jù)報文(datagram)可以調(diào)用socket.bind()
。socket.bind()
將會綁定到所有接口("all interfaces")的隨機端口上(udp4
和udp6
sockets都適用)。你可以通過socket.address().address
和socket.address().port
獲取地址和端口。
options
對象callback
函數(shù)。給message
事件添加事件監(jiān)聽器。參數(shù)options
必須包含type
值(udp4
或udp6
),或可選的boolean值reuseAddr
。
當(dāng)reuseAddr
為 true 時,socket.bind()
將會重用地址,即使另一個進程已經(jīng)綁定socket。reuseAddr
默認(rèn)為false
。
回調(diào)函數(shù)為可選參數(shù),作為message
事件的監(jiān)聽器。
如果你想接受數(shù)據(jù)報文(datagram),可以調(diào)用socket.bind()
。socket.bind()
將會綁定到所有接口("all interfaces")地址的隨機端口上(udp4
和udp6
sockets都適用)。你可以通過socket.address().address
和socket.address().port
獲取地址和端口。
報文數(shù)據(jù)Socket類封裝了數(shù)據(jù)報文(datagram)函數(shù)。必須通過dgram.createSocket(...)
函數(shù)創(chuàng)建。
msg
緩存對象. 消息。rinfo
對象. 遠(yuǎn)程地址信息。當(dāng)socket上新的數(shù)據(jù)報文(datagram)可用的時候,會觸發(fā)這個事件。msg
是一個緩存,rinfo
是一個包含發(fā)送者地址信息的對象。
socket.on('message', function(msg, rinfo) {
console.log('Received %d bytes from %s:%d\n',
msg.length, rinfo.address, rinfo.port);
});
當(dāng)socket開始監(jiān)聽數(shù)據(jù)報文(datagram)時觸發(fā)。在UDP socket創(chuàng)建時觸發(fā)。
當(dāng)socket使用close()
關(guān)閉時觸發(fā)。在這個socket上不會觸發(fā)新的消息事件。
exception
Error對象當(dāng)發(fā)生錯誤時觸發(fā)。
buf
緩存對象或字符串. 要發(fā)送的消息。offset
整數(shù)。消息在緩存中得偏移量。length
整數(shù)。消息的比特數(shù)。port
整數(shù)。端口的描述。address
字符串。目標(biāo)的主機名或IP地址。callback
函數(shù)。當(dāng)消息發(fā)送完畢的時候調(diào)用??蛇x。對于UDP socket,必須指定目標(biāo)端口和地址。address
參數(shù)可能是字符串,它會被DNS解析。
如果忽略地址或者地址是空字符串,將使用'0.0.0.0'
或'::0'
替代。依賴于網(wǎng)絡(luò)配置,這些默認(rèn)值有可能行也可能不行。
如果socket之前沒被調(diào)用bind
綁定,則它會被分配一個隨機端口并綁定到所有接口("all interfaces")地址(udp4
sockets的'0.0.0.0'
,udp6
sockets的'::0'
)
回調(diào)函數(shù)可能用來檢測DNS錯誤,或用來確定什么時候重用buf
對象。注意,DNS查詢會導(dǎo)致發(fā)送tick延遲。通過回調(diào)函數(shù)能確認(rèn)數(shù)據(jù)報文(datagram)是否已經(jīng)發(fā)送的。
考慮到多字節(jié)字符串情況,偏移量和長度是字節(jié)長度byte length,而不是字符串長度。
下面的例子是在localhost
上發(fā)送一個UDP包給隨機端口:
var dgram = require('dgram');
var message = new Buffer("Some bytes");
var client = dgram.createSocket("udp4");
client.send(message, 0, message.length, 41234, "localhost", function(err) {
client.close();
});
關(guān)于UDP數(shù)據(jù)報文(datagram) 尺寸
IPv4/v6
數(shù)據(jù)報文(datagram)的最大長度依賴于MTU
(Maximum Transmission Unit)和Payload Length
的長度。
Payload Length
內(nèi)容為16位寬,它意味著Payload的最大字節(jié)說不超過64k,其中包括了頭信息和數(shù)據(jù)(65,507字節(jié) = 65,535 ? 8字節(jié)UDP頭 ? 20字節(jié)IP 頭);對于環(huán)回接口(loopback interfaces)這是真的,但對于多數(shù)主機和網(wǎng)絡(luò)來說不太現(xiàn)實。
MTU
能支持?jǐn)?shù)據(jù)報文(datagram)的最大值(以目前鏈路層技術(shù)來說)。對于任何連接,IPv4
允許的最小值為68
的MTU
,推薦值為576
(通常推薦作撥號應(yīng)用的MTU
),無論他們是完整接收還是碎片接收。
對于IPv6
,MTU
的最小值為1280
字節(jié),最小碎片緩存大小為1500
字節(jié)。16字節(jié)實在是太小,所以目前鏈路層一般最小MTU
大小為1500
。
我們不可能知道一個包可能進過的每個連接的MTU。通常發(fā)送一個超過接收端MTU大小的數(shù)據(jù)報文(datagram)會失效。(數(shù)據(jù)包會被悄悄的拋棄,不會通知發(fā)送端數(shù)據(jù)包沒有到達(dá)接收端)。
port
整數(shù)address
字符串,可選callback
沒有參數(shù)的函數(shù),可選。綁定時會調(diào)用回調(diào)。對于UDP socket,在一個端口和可選地址上監(jiān)聽數(shù)據(jù)報文(datagram)。如果沒有指定地點,系統(tǒng)將會參數(shù)監(jiān)聽所有的地址。綁定完畢后,會觸發(fā)"listening" 事件,并會調(diào)用傳入的回調(diào)函數(shù)。指定監(jiān)聽事件和回調(diào)函數(shù)非常有用。
一個綁定了的數(shù)據(jù)報文socket會保持node進程運行來接收數(shù)據(jù)。
如果綁定失敗,會產(chǎn)生錯誤事件。極少數(shù)情況(比如綁定一個關(guān)閉的socket)。這個方法會拋出一個錯誤。
以下是UDP服務(wù)器監(jiān)聽端口41234的例子:
var dgram = require("dgram");
var server = dgram.createSocket("udp4");
server.on("error", function (err) {
console.log("server error:\n" + err.stack);
server.close();
});
server.on("message", function (msg, rinfo) {
console.log("server got: " + msg + " from " +
rinfo.address + ":" + rinfo.port);
});
server.on("listening", function () {
var address = server.address();
console.log("server listening " +
address.address + ":" + address.port);
});
server.bind(41234);
// server listening 0.0.0.0:41234
options
{對象} - 必需. 有以下的屬性:port
{Number} - 必需.address
{字符串} - 可選.exclusive
{Boolean} - 可選.callback
{函數(shù)} - 可選.options
的可選參數(shù)port
和 address
,以及可選參數(shù)callback
,好像在調(diào)用socket.bind(port, [address], [callback])。
如果exclusive
是false
(默認(rèn)),集群進程將會使用相同的底層句柄,允許連接處理共享的任務(wù)。當(dāng)exclusive
為true
時,句柄不會共享,嘗試共享端口也會失敗。監(jiān)聽exclusive
端口的例子如下:
socket.bind({
address: 'localhost',
port: 8000,
exclusive: true
});
關(guān)閉底層socket并且停止監(jiān)聽數(shù)據(jù)。
返回一個包含套接字地址信息的對象。對于UDP socket,這個對象會包含address
,family
和port
。
flag
Boolean設(shè)置或清除SO_BROADCAST
socket選項。設(shè)置這個選項后,UDP包可能會發(fā)送給一個本地的接口廣播地址。
ttl
整數(shù)設(shè)置IP_TTL
socket選項。TTL表示生存時間(Time to Live),但是在這個上下文中它指的是報文允許通過的IP躍點數(shù)。各個轉(zhuǎn)發(fā)報文的路由器或者網(wǎng)關(guān)都會遞減 TTL。如果TTL被路由器遞減為0,則它將不會被轉(zhuǎn)發(fā)。改變TTL的值通常用于網(wǎng)絡(luò)探測器或多播。
setTTL()
的參數(shù)為1到255的躍點數(shù)。多數(shù)系統(tǒng)默認(rèn)值為64。
ttl
整數(shù)設(shè)置IP_MULTICAST_TTL
socket選項。TTL表示生存時間(Time to Live),但是在這個上下文中它指的是報文允許通過的IP躍點數(shù)。各個轉(zhuǎn)發(fā)報文的路由器或者網(wǎng)關(guān)都會遞減TTL。如果TTL被路由器遞減為0,則它將不會被轉(zhuǎn)發(fā)。改變TTL的值通常用于網(wǎng)絡(luò)探測器或多播。
setMulticastTTL()
的參數(shù)為1到255的躍點數(shù)。多數(shù)系統(tǒng)默認(rèn)值為1。
flag
Boolean設(shè)置或清空IP_MULTICAST_LOOP
socket選項。設(shè)置完這個選項后,當(dāng)該選項被設(shè)置時,組播報文也會被本地接口收到。
multicastAddress
字符串multicastInterface
字符串,可選告訴內(nèi)核加入廣播組,選項為IP_ADD_MEMBERSHIP
socket
如果沒有指定multicastInterface
,操作系統(tǒng)會給所有可用的接口添加關(guān)系。
multicastAddress
字符串multicastInterface
字符串,可選和addMembership
相反 - 用IP_DROP_MEMBERSHIP
選項告訴內(nèi)核離開廣播組 。如果沒有指定multicastInterface
,操作系統(tǒng)會移除所有可用的接口關(guān)系。
在socket上調(diào)用unref
允許程序退出,如果這是在事件系統(tǒng)中唯一的活動socket。如果socket已經(jīng)unref
,再次調(diào)用unref
將會無效。
和unref
相反,如果這是唯一的socket,在一個之前被unref了的socket上調(diào)用ref將不會讓程序退出(缺省行為)。如果一個socket已經(jīng)被ref,則再次調(diào)用ref將會無效。
更多建議: