net
模塊為你提供了異步的網(wǎng)絡(luò)調(diào)用的包裝。它同時(shí)包含了創(chuàng)建服務(wù)器和客戶端的函數(shù)。你可以通過(guò)require('net')
來(lái)引入這個(gè)模塊。
創(chuàng)建一個(gè)新的TCP服務(wù)器。connectionListener
參數(shù)會(huì)被自動(dòng)綁定為connection
事件的監(jiān)聽(tīng)器。
options
是一個(gè)包含下列默認(rèn)值的對(duì)象:
{
allowHalfOpen: false,
pauseOnConnect: false
}
如果allowHalfOpen
是true
,那么當(dāng)另一端的socket
發(fā)送一個(gè)FIN
報(bào)文時(shí)socket
并不會(huì)自動(dòng)發(fā)送FIN
報(bào)文。socket
變得不可讀,但是可寫(xiě)。你需要明確地調(diào)用end()
方法。詳見(jiàn)end
事件。
如果pauseOnConnect
是true,那么socket
在每一次被連接時(shí)會(huì)暫停,并且不會(huì)讀取數(shù)據(jù)。這允許在進(jìn)程間被傳遞的連接不讀取任何數(shù)據(jù)。如果要讓一個(gè)被暫停的socket
開(kāi)始讀取數(shù)據(jù),調(diào)用resume()
方法。
以下是一個(gè)應(yīng)答服務(wù)器的例子,監(jiān)聽(tīng)8124端口:
var net = require('net');
var server = net.createServer(function(c) { //'connection' listener
console.log('client connected');
c.on('end', function() {
console.log('client disconnected');
});
c.write('hello\r\n');
c.pipe(c);
});
server.listen(8124, function() { //'listening' listener
console.log('server bound');
});
使用telnet
測(cè)試:
telnet localhost 8124
想要監(jiān)聽(tīng)socket``/tmp/echo.sock
,只需改變倒數(shù)第三行:
server.listen('/tmp/echo.sock', function() { //'listening' listener
使用nc
連接一個(gè)UNIX domain socket服務(wù)器:
nc -U /tmp/echo.sock
工廠函數(shù),返回一個(gè)新的net.Socket
實(shí)例,并且自動(dòng)使用提供的options
進(jìn)行連接。
options
會(huì)被同時(shí)傳遞給net.Socket
構(gòu)造函數(shù)和socket.connect
方法。
參數(shù)connectListener
將會(huì)被立即添加為connect
事件的監(jiān)聽(tīng)器。
下面是一個(gè)上文應(yīng)答服務(wù)器的客戶端的例子:
var net = require('net');
var client = net.connect({port: 8124},
function() { //'connect' listener
console.log('connected to server!');
client.write('world!\r\n');
});
client.on('data', function(data) {
console.log(data.toString());
client.end();
});
client.on('end', function() {
console.log('disconnected from server');
});
要連接socket``/tmp/echo.sock
只需要改變第二行為:
var client = net.connect({path: '/tmp/echo.sock'});
工廠函數(shù),返回一個(gè)新的net.Socket
實(shí)例,并且自動(dòng)使用指定的端口(port)和主機(jī)(host)進(jìn)行連接。
如果host
被省略,默認(rèn)為localhost
。
參數(shù)connectListener
將會(huì)被立即添加為connect
事件的監(jiān)聽(tīng)器。
工廠函數(shù),返回一個(gè)新的unixnet.Socket
實(shí)例,并且自動(dòng)使用提供的路徑(path)進(jìn)行連接。
參數(shù)connectListener
將會(huì)被立即添加為connect
事件的監(jiān)聽(tīng)器。
這個(gè)類用于創(chuàng)建一個(gè)TCP或本地服務(wù)器。
開(kāi)始從指定端口和主機(jī)名接收連接。如果省略主機(jī)名,那么如果IPv6可用,服務(wù)器會(huì)接受從任何IPv6地址(::)來(lái)的鏈接,否則為任何IPv4地址(0.0.0.0)。如果端口為0那么將會(huì)為其設(shè)置一個(gè)隨機(jī)端口。
積壓量backlog
是連接等待隊(duì)列的最大長(zhǎng)度。實(shí)際長(zhǎng)度由你的操作系統(tǒng)的sysctl
設(shè)置決定(如linux中的tcp_max_syn_backlog
和somaxconn
)。這個(gè)參數(shù)的默認(rèn)值是511(不是512)。
這個(gè)函數(shù)式異步的。當(dāng)服務(wù)器綁定了指定端口后,listening
事件將會(huì)被觸發(fā)。最后一個(gè)參數(shù)callback
將會(huì)被添加為listening
事件的監(jiān)聽(tīng)器。
有些用戶可能遇到的情況是收到EADDRINUSE
錯(cuò)誤。這意味著另一個(gè)服務(wù)器已經(jīng)使用了該端口。一個(gè)解決的辦法是等待一段時(shí)間后重試。
server.on('error', function (e) {
if (e.code == 'EADDRINUSE') {
console.log('Address in use, retrying...');
setTimeout(function () {
server.close();
server.listen(PORT, HOST);
}, 1000);
}
});
(注意,io.js
中所有的socket
都已經(jīng)設(shè)置了SO_REUSEADDR
)
啟動(dòng)一個(gè)本地socket
服務(wù)器,監(jiān)聽(tīng)指定路徑(path
)上的連接。
這個(gè)函數(shù)式異步的。當(dāng)服務(wù)器監(jiān)聽(tīng)了指定路徑后,listening
事件將會(huì)被觸發(fā)。最后一個(gè)參數(shù)callback
將會(huì)被添加為listening
事件的監(jiān)聽(tīng)器。
在UNIX中,local domain
經(jīng)常被稱作UNIX domain
。path
是一個(gè)文件系統(tǒng)路徑名。它在被創(chuàng)建時(shí)會(huì)受相同文件名約定(same naming conventions)的限制并且進(jìn)行權(quán)限檢查(permissions checks)。它在文件系統(tǒng)中可見(jiàn),并且在被刪除前持續(xù)存在。
在Windows中,local doamin
使用一個(gè)命名管道(named pipe)實(shí)現(xiàn)。path
必須指向\\?\pipe\
或\\.\pipe\.
中的一個(gè)條目,但是后者可能會(huì)做一些命名管道的處理,如處理..
序列。除去表現(xiàn),命名管道空間是平坦的(flat)。管道不會(huì)持續(xù)存在,它們將在最后一個(gè)它們的引用關(guān)閉后被刪除。不要忘記,由于JavaScript
的字符串轉(zhuǎn)義,你必須在指定path
時(shí)使用雙反斜杠:
net.createServer().listen(
path.join('\\\\?\\pipe', process.cwd(), 'myctl'))
handle
對(duì)象可以被設(shè)置為一個(gè)服務(wù)器或一個(gè)socket
(或者任意以下劃線開(kāi)頭的成員_handle
),或者一個(gè){fd: <n>}
對(duì)象。
這將使得服務(wù)器使用指定句柄接受連接,但它假設(shè)文件描述符或句柄已經(jīng)被綁定至指定的端口或域名socket
。
在Windows下不支持監(jiān)聽(tīng)一個(gè)文件描述符。
這個(gè)函數(shù)式異步的。當(dāng)服務(wù)器已被綁定后,listening
事件將會(huì)被觸發(fā)。最后一個(gè)參數(shù)callback
將會(huì)被添加為listening
事件的監(jiān)聽(tīng)器。
options Object
exclusive Boolean 可選
callback Function 可選
port
,host
和backlog
屬性,以及可選的callback
函數(shù),與server.listen(port, [host], [backlog], [callback])
中表現(xiàn)一致。path
可以被指定為一個(gè)UNIX socket
。
如果exclusive
是false
(默認(rèn)),那么工作集群(cluster workers)將會(huì)使用相同的底層句柄,處理的連接的職責(zé)將會(huì)被它們共享。如果exclusive
是true
,那么句柄是不被共享的,企圖共享將得到一個(gè)報(bào)錯(cuò)的結(jié)果。下面是一個(gè)監(jiān)聽(tīng)獨(dú)有端口的例子:
server.listen({
host: 'localhost',
port: 80,
exclusive: true
});
使服務(wù)器停止接收新的連接并且保持已存在的連接。這個(gè)函數(shù)式異步的,當(dāng)所有的連接都結(jié)束時(shí)服務(wù)器會(huì)最終關(guān)閉,并處罰一個(gè)close
事件??蛇x的,你可以傳遞一個(gè)回調(diào)函數(shù)來(lái)監(jiān)聽(tīng)close
事件。如果傳遞了,那么它的唯一的第一個(gè)參數(shù)將表示任何可能潛在發(fā)生的錯(cuò)誤。
返回服務(wù)器綁定的地址,協(xié)議族名和端口通過(guò)操作系統(tǒng)報(bào)告。對(duì)查找操作系統(tǒng)分配的地址哪個(gè)端口被分配非常有用。返回一個(gè)有三個(gè)屬性的對(duì)象。如{ port: 12346, family: 'IPv4', address: '127.0.0.1' }
。
例子:
var server = net.createServer(function (socket) {
socket.end("goodbye\n");
});
// grab a random port.
server.listen(function() {
address = server.address();
console.log("opened server on %j", address);
});
在listening
事件觸發(fā)前,不要調(diào)用server.address()
方法。
調(diào)用一個(gè)server
對(duì)象的unref
方法將允許如果它是事件系統(tǒng)中唯一活躍的服務(wù)器,程序?qū)?huì)退出。如果服務(wù)器已經(jīng)被調(diào)用過(guò)這個(gè)方法,那么再次調(diào)用這個(gè)方法將不會(huì)有任何效果。
返回server
對(duì)象。
與unref
相反,在一個(gè)已經(jīng)被調(diào)用unref
方法的server
中調(diào)用ref
方法,那么如果它是唯一活躍的服務(wù)器時(shí),程序?qū)⒉粫?huì)退出(默認(rèn))。如果服務(wù)器已經(jīng)被調(diào)用過(guò)這個(gè)方法,那么再次調(diào)用這個(gè)方法將不會(huì)有任何效果。
返回server
對(duì)象。
設(shè)置了這個(gè)屬性后,服務(wù)器的連接數(shù)達(dá)到時(shí)將會(huì)開(kāi)始拒絕連接。
一旦socket
被使用child_process.fork()
傳遞給了子進(jìn)程,這個(gè)屬性就不被推薦去設(shè)置。
這個(gè)函數(shù)已經(jīng)被棄用。請(qǐng)使用server.getConnections()
替代。
服務(wù)器的當(dāng)前連接數(shù)。
當(dāng)使用child_process.fork()
傳遞一個(gè)socket
給子進(jìn)程時(shí),這個(gè)屬性將變成null
。想要得到正確的結(jié)果請(qǐng)使用server.getConnections
。
異步地去獲取服務(wù)器的當(dāng)前連接數(shù),在socket
被傳遞給子進(jìn)程時(shí)仍然可用。
回調(diào)函數(shù)的兩個(gè)參數(shù)是err
和count
。
net.Server
是一個(gè)具有以下事件的EventEmitter
:當(dāng)調(diào)用server.listen
后,服務(wù)器已被綁定時(shí)觸發(fā)。
當(dāng)新的連接產(chǎn)生時(shí)觸發(fā)。socket
是一個(gè)net.Socket
實(shí)例。
當(dāng)服務(wù)器關(guān)閉時(shí)觸發(fā)。注意如果服務(wù)器中仍有連接存在,那么這個(gè)事件會(huì)直到所有的連接都關(guān)閉后才觸發(fā)。
當(dāng)發(fā)生錯(cuò)誤時(shí)觸發(fā)。close
事件將會(huì)在它之后立即觸發(fā)。參閱server.listen
。
這個(gè)對(duì)象是一個(gè)TCP或本地socket
的抽象。net.Socket
實(shí)例實(shí)現(xiàn)了雙工流(duplex Stream)接口。它可以被使用者創(chuàng)建,并且被作為客戶端(配合connect()
)使用?;蛘咭部梢员?code>io.js創(chuàng)建,并且通過(guò)服務(wù)器的connection
事件傳遞給使用者。
創(chuàng)建一個(gè)新的socket
對(duì)象。
options
是一個(gè)有以下默認(rèn)值的對(duì)象:
{ fd: null
allowHalfOpen: false,
readable: false,
writable: false
}
fd
允許你使用一個(gè)指定的已存在的socket
文件描述符。設(shè)置readable
和/或 writable
為true
將允許從這個(gè)socket
中讀 和/或 寫(xiě)(注意,僅在傳遞了passed
時(shí)可用)。關(guān)于allowHalfOpen
,參閱createServer()
和end
事件。
從給定的socket
打開(kāi)一個(gè)連接。
對(duì)于TCPsocket
,options
參數(shù)需是一個(gè)包含以下屬性的對(duì)象:
port: 客戶端需要連接的端口(必選)。
host: 客戶端需要連接的主機(jī)(默認(rèn):'localhost')
localAddress: 將要綁定的本地接口,為了網(wǎng)絡(luò)連接。
localPort: 將要綁定的本地端口,為了網(wǎng)絡(luò)連接。
family : IP協(xié)議族版本,默認(rèn)為4
。
lookup : 自定義查找函數(shù)。默認(rèn)為dns.lookup
。
對(duì)于本地domain socket
,options
參數(shù)需是一個(gè)包含以下屬性的對(duì)象:
通常這個(gè)方法是不需要的,因?yàn)橥ㄟ^(guò)net.createConnection
打開(kāi)socket
。只有在你自定義了socket
時(shí)才使用它。
這個(gè)函數(shù)式異步的,當(dāng)connect
事件觸發(fā)時(shí),這個(gè)socket
就被建立了。如果在連接的過(guò)程有問(wèn)題,那么connect
事件將不會(huì)觸發(fā),error
將會(huì)帶著這個(gè)異常觸發(fā)。
connectListener
參數(shù)會(huì)被自動(dòng)添加為connect
事件的監(jiān)聽(tīng)器。
參閱socket.connect(options[, connectListener])
。
net.Socket
的屬性,用于socket.write()
。它可以幫助用戶獲取更快的運(yùn)行速度。計(jì)算機(jī)不能一直保持大量數(shù)據(jù)被寫(xiě)入socket
的狀態(tài),網(wǎng)絡(luò)連接可以很慢。io.js
在內(nèi)部會(huì)排隊(duì)等候數(shù)據(jù)被寫(xiě)入socekt
并確保傳輸連接上的數(shù)據(jù)完好。 (內(nèi)部實(shí)現(xiàn)為:輪詢socekt
的文件描述符等待它為可寫(xiě))。
內(nèi)部緩存的可能結(jié)果是內(nèi)存使用會(huì)增長(zhǎng)。這個(gè)屬性展示了緩存中還有多少待寫(xiě)入的字符(字符的數(shù)目約等于要被寫(xiě)入的字節(jié)數(shù),但是緩沖區(qū)可能包含字符串,而字符串是惰性編碼的,所以確切的字節(jié)數(shù)是未知的)。
遇到數(shù)值很大或增長(zhǎng)很快的bufferSize
時(shí),應(yīng)當(dāng)嘗試使用pause()
和resume()
來(lái)控制。
設(shè)置socket
的編碼作為一個(gè)可讀流。詳情參閱stream.setEncoding()
。
在套接字上發(fā)送數(shù)據(jù)。第二個(gè)參數(shù)指定了字符串的編碼,默認(rèn)為UTF8。
如果所有數(shù)據(jù)成功被刷新至了內(nèi)核緩沖區(qū),則返回true
。如果所有或部分?jǐn)?shù)據(jù)仍然在用戶內(nèi)存中排隊(duì),則返回false
。drain
事件將會(huì)被觸發(fā)當(dāng)buffer
再次為空時(shí)。
當(dāng)數(shù)據(jù)最終被寫(xiě)入時(shí),callback
回調(diào)函數(shù)將會(huì)被執(zhí)行,但可能不會(huì)馬上執(zhí)行。
半關(guān)閉一個(gè)socket
。比如,它發(fā)送一個(gè)FIN
報(bào)文??赡芊?wù)器仍然在發(fā)送一些數(shù)據(jù)。
如果data
參數(shù)被指定,那么等同于先調(diào)用socket.write(data, encoding)
,再調(diào)用socket.end()
。
確保這個(gè)socket
上沒(méi)有I/O活動(dòng)發(fā)生。只在發(fā)生錯(cuò)誤情況才需要(如處理錯(cuò)誤)。
暫停數(shù)據(jù)讀取。data
事件將不會(huì)再觸發(fā)。對(duì)于控制上傳非常有用。
用于在調(diào)用pause()
后,恢復(fù)數(shù)據(jù)讀取。
如果socket
在timeout
毫秒中沒(méi)有活動(dòng)后,設(shè)置其為超時(shí)。默認(rèn)情況下,net.Socket
沒(méi)有超時(shí)。
當(dāng)超時(shí)發(fā)生,socket
會(huì)收到一個(gè)timeout
事件,但是連接將不會(huì)被斷開(kāi)。用戶必須手動(dòng)地調(diào)用end()
或destroy()
方法。
如果timeout
是0
,那么現(xiàn)有的超時(shí)將會(huì)被禁用。
可選的callback
參數(shù)就會(huì)被自動(dòng)添加為timeout
事件的監(jiān)聽(tīng)器。
返回一個(gè)socket
。
警用納格算法(Nagle algorithm)。默認(rèn)情況下TCP連接使用納格算法,它們的數(shù)據(jù)在被發(fā)送前會(huì)被緩存。設(shè)置noDelay
為true
將會(huì)在每次socket.write()
時(shí)立刻發(fā)送數(shù)據(jù)。noDelay
默認(rèn)為true
。
返回一個(gè)socket
。
啟用/警用長(zhǎng)連接功能,并且在第一個(gè)在閑置socket
的長(zhǎng)連接probe
被發(fā)送前,可選得設(shè)置初始延時(shí)。enable
默認(rèn)為false
。
設(shè)定initialDelay
(毫秒),來(lái)設(shè)定在收到的最后一個(gè)數(shù)據(jù)包和第一個(gè)長(zhǎng)連接probe
之間的延時(shí)。將initialDelay
設(shè)成0
會(huì)讓值保持不變(默認(rèn)值或之前所設(shè)的值)。默認(rèn)為0
。
返回一個(gè)socket
。
返回綁定的地址,協(xié)議族名和端口通過(guò)操作系統(tǒng)報(bào)告。對(duì)查找操作系統(tǒng)分配的地址哪個(gè)端口被分配非常有用。返回一個(gè)有三個(gè)屬性的對(duì)象。如{ port: 12346, family: 'IPv4', address: '127.0.0.1' }
。
調(diào)用一個(gè)socket
對(duì)象的unref
方法將允許如果它是事件系統(tǒng)中唯一活躍的socket
,程序?qū)?huì)退出。如果socket
已經(jīng)被調(diào)用過(guò)這個(gè)方法,那么再次調(diào)用這個(gè)方法將不會(huì)有任何效果。
返回socket
對(duì)象。
與unref
相反,在一個(gè)已經(jīng)被調(diào)用unref
方法的socket
中調(diào)用ref
方法,那么如果它是唯一活躍的socket
時(shí),程序?qū)⒉粫?huì)退出(默認(rèn))。如果socket
已經(jīng)被調(diào)用過(guò)這個(gè)方法,那么再次調(diào)用這個(gè)方法將不會(huì)有任何效果。
返回socket
對(duì)象。
遠(yuǎn)程IP地址字符串。例如,'74.125.127.100'
或'2001:4860:a005::68'
。
遠(yuǎn)程IP協(xié)議族字符串。例如,'IPv4'
或'IPv6'
。
遠(yuǎn)程端口數(shù)值。例如,80
或21
。
遠(yuǎn)程客戶端正連接的本地IP地址字符串。例如,如果你正在監(jiān)聽(tīng)'0.0.0.0'
并且客戶端連接在'192.168.1.1'
,其值將為'192.168.1.1'
。
本地端口數(shù)值。例如,80
或21
。
接受的字節(jié)數(shù)。
發(fā)送的字節(jié)數(shù)。
net.Socket
實(shí)例是一個(gè)包含以下事件的EventEmitter
:在解析主機(jī)名后,連接主機(jī)前觸發(fā)。對(duì)UNIX socket
不適用。
dns.lookup()
在socket
連接成功建立后觸發(fā)。參閱connect()
。
在接受到數(shù)據(jù)后觸發(fā)。參數(shù)將會(huì)是一個(gè)Buffer
或一個(gè)字符串。數(shù)據(jù)的編碼由socket.setEncoding()
設(shè)置(更多詳細(xì)信息請(qǐng)查看可讀流章節(jié))。
注意,當(dāng)socket
觸發(fā)data
事件時(shí),如果沒(méi)有監(jiān)聽(tīng)器存在。那么數(shù)據(jù)將會(huì)丟失。
當(dāng)另一端的socket
發(fā)送一個(gè)FIN
報(bào)文時(shí)觸發(fā)。
默認(rèn)情況(allowHalfOpen == false
)下,一旦一個(gè)socket
的文件描述符被從它的等待寫(xiě)隊(duì)列(pending write queue)中寫(xiě)出,socket
會(huì)銷毀它。但是,當(dāng)設(shè)定allowHalfOpen == true
后,socket
不會(huì)在它這邊自動(dòng)調(diào)用end()
,允許用戶寫(xiě)入任意數(shù)量的數(shù)據(jù),需要注意的是用戶需要在自己這邊調(diào)用end()
。
當(dāng)socket
因不活動(dòng)而超時(shí)時(shí)觸發(fā)。這只是來(lái)表示socket
被限制。用戶必須手動(dòng)關(guān)閉連接。
參閱socket.setTimeout()
。
當(dāng)寫(xiě)緩沖為空時(shí)觸發(fā)??梢员挥脕?lái)控制上傳流量。
參閱socket.write()
的返回值。
當(dāng)發(fā)生錯(cuò)誤時(shí)觸發(fā)。close
事件會(huì)緊跟著這個(gè)事件觸發(fā)。
socket
有一個(gè)傳輸錯(cuò)誤時(shí)為true
當(dāng)socket
完全關(guān)閉時(shí)觸發(fā)。參數(shù)had_error
是一個(gè)表示socket
是否是因?yàn)閭鬏斿e(cuò)誤而關(guān)閉的布爾值。
測(cè)試input
是否是一個(gè)IP地址。如果是不合法字符串時(shí),會(huì)返回0
。如果是IPv4地址則返回4
,是IPv6地址則返回6
。
如果input
是一個(gè)IPv4地址則返回true
,否則返回false
。
如果input
是一個(gè)IPv6地址則返回true
,否則返回false
。
更多建議: