Node.js 網(wǎng)絡(luò)

2022-02-26 10:31 更新
穩(wěn)定性: 3 - 穩(wěn)定

net模塊提供了異步網(wǎng)絡(luò)封裝,該Node.js模塊包含了創(chuàng)建服務(wù)器/客戶端的方法(調(diào)用 streams),你可以通過調(diào)用 require('net') 包含這個模塊,訪問方法如下所示:

const net = require('net');

net.createServer([options][, connectionListener])

創(chuàng)建一個TCP服務(wù)器。參數(shù)connectionListener自動給'connection'事件創(chuàng)建監(jiān)聽器。

options包含有以下默認(rèn)值:

{
  allowHalfOpen: false,
  pauseOnConnect: false
}

如果allowHalfOpen=true,當(dāng)另一端socket發(fā)送FIN包時,socket不會自動發(fā)送FIN包。socket變?yōu)椴豢勺x,但仍可寫。你需要顯式的調(diào)用end()方法。更多信息參見'end'事件。

如果pauseOnConnect=true,當(dāng)連接到來的時候相關(guān)聯(lián)的socket將會暫停。它允許在初始進(jìn)程不讀取數(shù)據(jù)情況下,讓連接在進(jìn)程間傳遞。調(diào)用resume()從暫停的socket里讀取數(shù)據(jù)。

下面是一個監(jiān)聽8124端口連接的應(yīng)答服務(wù)器的例子:

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來測試:

telnet localhost 8124

要監(jiān)聽socket t/tmp/echo.sock,僅需要改倒數(shù)第三行代碼,如下所示:

server.listen('/tmp/echo.sock', function() { //'listening' listener

使用nc連接到一個UNIX domain socket服務(wù)器:

nc -U /tmp/echo.sock

net.connect(options[, connectionListener])

net.createConnection(options[, connectionListener])

工廠方法,返回一個新的'net.Socket',并連接到指定的地址和端口。

當(dāng)socket建立的時候,將會觸發(fā)'connect'事件。

'net.Socket'有相同的方法。

對于TCP sockets,參數(shù)options因?yàn)橄铝袇?shù)的對象:

  • port: 客戶端連接到Port的端口(必須)。

  • host: 客戶端要連接到得主機(jī)。默認(rèn)'localhost'.

  • localAddress: 網(wǎng)絡(luò)連接綁定的本地接口。

  • localPort: 網(wǎng)絡(luò)連接綁定的本地端口。

  • family : IP棧版本。默認(rèn)4。

對于本地域socket,參數(shù)options因?yàn)橄铝袇?shù)的對象:

  • path: 客戶端連接到得路徑(必須).

通用選項(xiàng):

  • 如果allowHalfOpen=true, 當(dāng)另一端socket發(fā)送FIN包時socket不會自動發(fā)送FIN包。socket變?yōu)椴豢勺x,但仍可寫。你需要顯式的調(diào)用end()方法。更多信息參見'end'事件。

    connectListener參數(shù)將會作為監(jiān)聽器添加到'connect'事件上。

下面是一個用上述方法應(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,僅需將第二行代碼改為如下的內(nèi)容:

var client = net.connect({path: '/tmp/echo.sock'});

net.connect(port[, host][, connectListener])

net.createConnection(port[, host][, connectListener])

創(chuàng)建一個到端口port和主機(jī)host的TCP連接。如果忽略主機(jī)host,則假定為'localhost'。參數(shù)connectListener將會作為監(jiān)聽器添加到'connect'事件。

這是工廠方法,返回一個新的'net.Socket'

net.connect(path[, connectListener])

net.createConnection(path[, connectListener])

創(chuàng)建到path的unix socket連接。參數(shù)connectListener將會作為監(jiān)聽器添加到'connect'事件上。

這是工廠方法,返回一個新的'net.Socket'

Class: net.Server

這個類用來創(chuàng)建一個TCP或本地服務(wù)器。

server.listen(port[, host][, backlog][, callback])

開始接受指定端口port和主機(jī)host的連接。如果忽略主機(jī)host, 服務(wù)器將會接受任何IPv4地址(INADDR_ANY)的直接連接。端口為0,則會分配一個隨機(jī)端口。

積壓量(Backlog)為連接等待隊(duì)列的最大長度。實(shí)際長度由您的操作系統(tǒng)通過 sysctl 設(shè)定,比如 linux 上的tcp_max_syn_backlogsomaxconn。這個參數(shù)默認(rèn)值是511(不是512)。

這是異步函數(shù)。當(dāng)服務(wù)器被綁定時會觸發(fā)'listening'事件。最后一個參數(shù)callback將會作為'listening'事件的監(jiān)聽器。

有些用戶會遇到EADDRINUSE錯誤,它表示另外一個服務(wù)器已經(jīng)運(yùn)行在所請求的端口上。處理這個情況的辦法是等一段事件再重試:

server.on('error', function (e) {
  if (e.code == 'EADDRINUSE') {
    console.log('Address in use, retrying...');
    setTimeout(function () {
      server.close();
      server.listen(PORT, HOST);
    }, 1000);
  }
});

(注意:Node中的所有socket已設(shè)置了SO_REUSEADDR)

server.listen(path[, callback])

  • path {String}
  • callback {Function}

啟動一個本地socket服務(wù)器,監(jiān)聽指定path的連接。

這是異步函數(shù)。綁定服務(wù)器后,會觸發(fā)'listening'事件。最后一個參數(shù)callback將會作為'listening'事件的監(jiān)聽器。

UNIX上,本地域通常默認(rèn)為UNIX域。參數(shù)path是文件系統(tǒng)路徑,就和創(chuàng)建文件時一樣,它也遵從命名規(guī)則和權(quán)限檢查,并且在文件系統(tǒng)里可見,并持續(xù)到關(guān)閉關(guān)聯(lián)。

Windows上,本地域通過命名管道實(shí)現(xiàn)。路徑必須是以\\?\pipe\\\.\pipe\入口。任意字符串都可以,不過之后進(jìn)行相同的管道命名處理,比如解決..序列。管道命名空間是平的。管道不會一直持久,當(dāng)最后一個引用關(guān)閉的時候,管道將會移除。不要忘記javascript字符字符串轉(zhuǎn)義要求路徑使用雙反斜杠,比如:

net.createServer().listen(
    path.join('\\\\?\\pipe', process.cwd(), 'myctl'))

server.listen(handle[, callback])

  • handle {Object}
  • callback {Function}

    handle 對象可以設(shè)置成server或socket(任意以下劃線_handle開頭的類),或者是{fd: <n>}對象。

這將是服務(wù)器用指定的句柄接收連接,前提是文件描述符或句柄已經(jīng)綁定到端口或域socket。

Windows不支持監(jiān)聽文件句柄。

這是異步函數(shù)。當(dāng)服務(wù)器已經(jīng)被綁定,將會觸發(fā)'listening'事件。最后一個參數(shù)callback將會作為'listening'事件的監(jiān)聽器。

server.listen(options[, callback])

  • options {Object} - 必須有。支持以下屬性:
    • port {Number} - 可選。
    • host {String} - 可選。
    • backlog {Number} - 可選。
    • path {String} - 可選。
    • exclusive {Boolean} - 可選。
  • callback {Function} - 可選。

options的屬性:端口port,主機(jī)host,和backlog,以及可選參數(shù)callback函數(shù),他們在一起調(diào)用server.listen(port, [host], [backlog], [callback])。還有,參數(shù)path可以用來指定UNIX socket。

如果參數(shù)exclusivefalse(默認(rèn)值),集群進(jìn)程將會使用同一個句柄,允許連接共享。當(dāng)參數(shù)exclusivetrue時,句柄不會共享,如果共享端口會返回錯誤。監(jiān)聽獨(dú)家端口例子如下:

server.listen({
  host: 'localhost',
  port: 80,
  exclusive: true
});

server.close([callback])

服務(wù)器停止接收新的連接,保持現(xiàn)有連接。這是異步函數(shù),當(dāng)所有連接結(jié)束的時候服務(wù)器會關(guān)閉,并會觸發(fā)'close'事件。你可以傳一個回調(diào)函數(shù)來監(jiān)聽'close' 事件。如果存在,將會調(diào)用回調(diào)函數(shù),錯誤(如果有)作為唯一參數(shù)。

server.address()

操作系統(tǒng)返回綁定的地址,協(xié)議族名和服務(wù)器端口。查找哪個端口已經(jīng)被系統(tǒng)綁定時,非常有用。返回的對象有3個屬性,比如:{ 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()。

server.unref()

如果這是事件系統(tǒng)中唯一一個活動的服務(wù)器,調(diào)用unref將允許程序退出。如果服務(wù)器已被unref,則再次調(diào)用unref并不會產(chǎn)生影響。

server.ref()

unref相反,如果這是唯一的服務(wù)器,在之前被unref了的服務(wù)器上調(diào)用ref將不會讓程序退出(默認(rèn)行為)。如果服務(wù)器已經(jīng)被ref,則再次調(diào)用ref并不會產(chǎn)生影響。

server.maxConnections

設(shè)置這個選項(xiàng)后,當(dāng)服務(wù)器連接數(shù)超過數(shù)量時拒絕新連接。

一旦已經(jīng)用child_process.fork()方法將socket發(fā)送給子進(jìn)程, 就不推薦使用這個選項(xiàng)。

server.connections

已經(jīng)拋棄這個函數(shù)。請用server.getConnections()代替。服務(wù)器上當(dāng)前連接的數(shù)量。

當(dāng)調(diào)用child_process.fork()發(fā)送一個socket給子進(jìn)程時,它將變?yōu)?code>null。 要輪詢子進(jìn)程來獲取當(dāng)前活動連接的數(shù)量,請用server.getConnections代替。

server.getConnections(callback)

異步獲取服務(wù)器當(dāng)前活躍連接的數(shù)量。當(dāng)socket發(fā)送給子進(jìn)程后才有效;

回調(diào)函數(shù)有2個參數(shù)errcount。

net.Server是事件分發(fā)器EventEmitter, 有以下事件:

事件: 'listening'

當(dāng)服務(wù)器調(diào)用server.listen綁定后會觸發(fā)。

事件:'connection'

  • {Socket object} 連接對象

當(dāng)新連接創(chuàng)建后會被觸發(fā)。socketnet.Socket實(shí)例。

事件: 'close'

服務(wù)器關(guān)閉時會觸發(fā)。注意,如果存在連接,這個事件不會被觸發(fā)直到所有的連接關(guān)閉。

事件: 'error'

  • {Error Object}

發(fā)生錯誤時觸發(fā)。'close'事件將被下列事件直接調(diào)用。請查看server.listen例子。

Class: net.Socket

這個對象是TCP或UNIX Socket的抽象。net.Socket實(shí)例實(shí)現(xiàn)了一個雙工流接口。他們可以在用戶創(chuàng)建客戶端(使用connect())時使用,或者由Node創(chuàng)建它們,并通過connection服務(wù)器事件傳遞給用戶。

new net.Socket([options])

構(gòu)造一個新的socket對象。

options對象有以下默認(rèn)值:

{ fd: null
  allowHalfOpen: false,
  readable: false,
  writable: false
}

參數(shù)fd允許你指定一個存在的文件描述符。將readable和(或)writable設(shè)為true,允許在這個socket上讀和(或)寫(注意,僅在參數(shù)fd有效時)。關(guān)于allowHalfOpen,參見createServer()'end'事件。

socket.connect(port[, host][, connectListener])

socket.connect(path[, connectListener])

使用傳入的socket打開一個連接。如果指定了端口port和主機(jī)host,TCP socket將打開socket。如果忽略參數(shù)host,則默認(rèn)為localhost。如果指定了 path,socket將會被指定路徑的unix socket打開。

通常情況不需要使用這個函數(shù),比如使用net.createConnection打開socket。只有你實(shí)現(xiàn)了自己的socket時才會用到。

這是異步函數(shù)。當(dāng)'connect'事件被觸發(fā)時,socket已經(jīng)建立。如果這是問題連接,'connect'事件不會被觸發(fā),將會拋出'error'事件。

參數(shù)connectListener將會作為監(jiān)聽器添加到'connect'事件。

socket.bufferSize

socket.bufferSize是net.Socket的一個屬性,用于socket.write()。它能夠幫助用戶獲取更快的運(yùn)行速度。計(jì)算機(jī)不能一直處于寫入大量數(shù)據(jù)狀態(tài)--網(wǎng)絡(luò)連接可能太慢。Node在內(nèi)部會將排隊(duì)數(shù)據(jù)寫入到socket,并在網(wǎng)絡(luò)可用時發(fā)送。(內(nèi)部實(shí)現(xiàn):輪詢socket的文件描述符直到變?yōu)榭蓪懀?/p>

這種內(nèi)部緩沖的缺點(diǎn)是會增加內(nèi)存使用量。這個屬性表示當(dāng)前準(zhǔn)備寫的緩沖字符數(shù)。(字符的數(shù)量等于準(zhǔn)備寫入的字節(jié)的數(shù)量,但是緩沖區(qū)可能包含字符串,這些字符串是惰性編碼的,所以準(zhǔn)確的字節(jié)數(shù)還無法知道)。

遇到很大增長很快的bufferSize時,用戶可用嘗試用pause()resume()來控制字符流。

socket.setEncoding([encoding])

設(shè)置socket的編碼為可讀流。更多信息參見stream.setEncoding()

socket.write(data[, encoding][, callback])

在socket上發(fā)送數(shù)據(jù)。第二個參數(shù)指定了字符串的編碼,默認(rèn)是UTF8編碼。

如果所有數(shù)據(jù)成功刷新到內(nèi)核緩沖區(qū),返回true。如果數(shù)據(jù)全部或部分在用戶內(nèi)存里,返回false。當(dāng)緩沖區(qū)為空的時候會觸發(fā)'drain'

當(dāng)數(shù)據(jù)最終被完整寫入的的時候,可選的callback參數(shù)會被執(zhí)行,但不一定會馬上執(zhí)行。

socket.end([data][, encoding])

半關(guān)閉socket。例如,它發(fā)送一個FIN包??赡芊?wù)器仍在發(fā)送數(shù)據(jù)。

如果參數(shù)data不為空,等同于調(diào)用socket.write(data, encoding)后再調(diào)用socket.end()。

socket.destroy()

確保沒有I/O活動在這個套接字上。只有在錯誤發(fā)生情況下才需要。(處理錯誤等等)。

socket.pause()

暫停讀取數(shù)據(jù)。就是說,不會再觸發(fā)data事件。對于控制上傳非常有用。

socket.resume()

調(diào)用pause()后想恢復(fù)讀取數(shù)據(jù)。

socket.setTimeout(timeout[, callback])

socket閑置時間超過timeout毫秒后 ,將socket設(shè)置為超時。

觸發(fā)空閑超時事件時,socket將會收到'timeout'事件,但是連接不會被斷開。用戶必須手動調(diào)用end()destroy()這個socket。

如果timeout= 0,那么現(xiàn)有的閑置超時會被禁用

可選的callback參數(shù)將會被添加成為'timeout'事件的一次性監(jiān)聽器。

socket.setNoDelay([noDelay])

禁用納格(Nagle)算法。默認(rèn)情況下TCP連接使用納格算法,在發(fā)送前他們會緩沖數(shù)據(jù)。將noDelay設(shè)置為true將會在調(diào)用socket.write()時立即發(fā)送數(shù)據(jù)。noDelay默認(rèn)值為true

socket.setKeepAlive([enable][, initialDelay])

禁用/啟用長連接功能,并在發(fā)送第一個在閑置socket上的長連接 probe 之前,可選地設(shè)定初始延時。默認(rèn)為false。

設(shè)定initialDelay(毫秒),來設(shè)定收到的最后一個數(shù)據(jù)包和第一個長連接probe之間的延時。將initialDelay設(shè)為0,將會保留默認(rèn)(或者之前)的值。默認(rèn)值為0。

socket.address()

操作系統(tǒng)返回綁定的地址,協(xié)議族名和服務(wù)器端口。返回的對象有3個屬性,比如{ port: 12346, family: 'IPv4', address: '127.0.0.1' }。

socket.unref()

如果這是事件系統(tǒng)中唯一一個活動的服務(wù)器,調(diào)用unref將允許程序退出。如果服務(wù)器已被unref,則再次調(diào)用unref并不會產(chǎn)生影響。

socket.ref()

unref相反,如果這是唯一的服務(wù)器,在之前被unref了的服務(wù)器上調(diào)用ref將不會讓程序退出(默認(rèn)行為)。如果服務(wù)器已經(jīng)被ref,則再次調(diào)用ref并不會產(chǎn)生影響。

socket.remoteAddress

遠(yuǎn)程的IP地址字符串,例如:'74.125.127.100'或者'2001:4860:a005::68'。

socket.remoteFamily

遠(yuǎn)程IP協(xié)議族字符串,比如'IPv4'或者'IPv6'。

socket.remotePort

遠(yuǎn)程端口,數(shù)字表示,例如:80或者21

socket.localAddress

網(wǎng)絡(luò)連接綁定的本地接口遠(yuǎn)程客戶端正在連接的本地IP地址,字符串表示。例如,如果你在監(jiān)聽'0.0.0.0'而客戶端連接在'192.168.1.1',這個值就會是 '192.168.1.1'。

socket.localPort

本地端口地址,數(shù)字表示。例如:80或者21。

socket.bytesRead

接收到得字節(jié)數(shù)。

socket.bytesWritten

發(fā)送的字節(jié)數(shù)。

net.Socket是事件分發(fā)器EventEmitter的實(shí)例, 有以下事件:

事件: 'lookup'

在解析域名后,但在連接前,觸發(fā)這個事件。對UNIX sokcet不適用。

  • err {Error | Null} 錯誤對象。參見dns.lookup().
  • address {String} IP地址。
  • family {String | Null} 地址類型。參見dns.lookup().

事件: 'connect'

當(dāng)成功建立socket連接時觸發(fā)。參見connect()。

事件: 'data'

  • {Buffer object}

當(dāng)接收到數(shù)據(jù)時觸發(fā)。參數(shù)data可以是BufferString。使用socket.setEncoding()設(shè)定數(shù)據(jù)編碼。(更多信息參見Readable Stream)。

當(dāng)Socket觸發(fā)一個'data'事件時,如果沒有監(jiān)聽器,數(shù)據(jù)將會丟失。

事件: 'end'

當(dāng)socket另一端發(fā)送FIN包時,觸發(fā)該事件。

默認(rèn)情況下(allowHalfOpen == false),一旦socket將隊(duì)列里的數(shù)據(jù)寫完畢,socket將會銷毀它的文件描述符。如果allowHalfOpen == true,socket不會從它這邊自動調(diào)用end(),使的用戶可以隨意寫入數(shù)據(jù),而讓用戶端自己調(diào)用end()。

事件: 'timeout'

當(dāng)socket空閑超時時觸發(fā),僅是表明socket已經(jīng)空閑。用戶必須手動關(guān)閉連接。

參見:socket.setTimeout()

事件: 'drain'

當(dāng)寫緩存為空得時候觸發(fā)??捎脕砜刂粕蟼?。

參見:socket.write()的返回值。

事件: 'error'

  • {Error object}

錯誤發(fā)生時觸發(fā)。以下事件將會直接觸發(fā)'close'事件。

事件: 'close'

  • had_error {Boolean} 如果socket傳輸錯誤,為true

當(dāng)socket完全關(guān)閉時觸發(fā)。參數(shù)had_error是boolean,它表示是否因?yàn)閭鬏斿e誤導(dǎo)致socket關(guān)閉。

net.isIP(input)

測試是否輸入的為IP地址。字符串無效時返回0。IPV4情況下返回4,IPV6情況下返回6.

net.isIPv4(input)

如果輸入的地址為IPV4,返回true,否則返回false。

net.isIPv6(input)

如果輸入的地址為IPV6,返回true,否則返回false。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號