# net
~~~
穩定度: 3 - 穩定
~~~
The `net` module provides you with an asynchronous network wrapper. It contains methods for creating both servers and clients (called streams). You can include this module with `require('net');`
### net.createServer([options], [connectionListener])
創建一個新的 TCP 服務器。參數 `connectionListener` 會被自動作為 ['connection'](#) 事件的監聽器。
`options` 是一個包含下列缺省值的對象:
~~~
{ allowHalfOpen: false
}
~~~
如果允許半開連接 `allowHalfOpen` 被設置為 `true`,則當另一端的套接字發送 FIN 報文時套接字并不會自動發送 FIN 報文。套接字會變為不可讀,但仍然可寫。您應當明確地調用 `end()` 方法。詳見 ['end'](#) 事件。
下面是一個監聽 8124 端口連接的應答服務器的例子:
~~~
var net = require('net');
var server = net.createServer(function(c) { // 'connection' 監聽器
console.log('服務器已連接');
c.on('end', function() {
console.log('服務器已斷開');
});
c.write('hello\r\n');
c.pipe(c);
});
server.listen(8124, function() { // 'listening' 監聽器
console.log('服務器已綁定');
});
~~~
使用 `telnet` 測試:
~~~
telnet localhost 8124
~~~
要監聽套接字 `/tmp/echo.sock` 僅需更改倒數第三行代碼:
~~~
server.listen('/tmp/echo.sock', function() { // 'listening' 監聽器
~~~
使用 `nc` 連接到一個 UNIX domain 套接字服務器:
~~~
nc -U /tmp/echo.sock
~~~
### net.connect(options, [connectionListener])
### net.createConnection(options, [connectionListener])
構建一個新的套接字對象并打開所給位置的套接字。當套接字就緒時會觸發 ['connect'](#) 事件。
對于 TCP 套接字,選項 `options` 參數應為一個指定下列參數的對象:
- `port`:客戶端連接到的端口(必須)
- `host`:客戶端連接到的主機,缺省為 `'localhost'`
- `localAddress`:網絡連接綁定的本地接口
- `family`:IP 棧版本,缺省為 `4`
對于 UNIX domain 套接字,選項 `options` 參數應當為一個指定下列參數的對象:
- `path`:客戶端連接到的路徑(必須)
通用選項:
- `allowHalfOpen`:允許半開連接,如果被設置為 `true`,則當另一端的套接字發送 FIN 報文時套接字并不會自動發送 FIN 報文。缺省為 `false`。詳見 ['end'](#) 事件。
`connectListener` 用于 ['connect'](#) 事件的監聽器
下面是一個上述應答服務器的客戶端的例子:
~~~
var net = require('net');
var client = net.connect({port: 8124},
function() { //'connect' 監聽器
console.log('client connected');
client.write('world!\r\n');
});
client.on('data', function(data) {
console.log(data.toString());
client.end();
});
client.on('end', function() {
console.log('客戶端斷開連接');
});
~~~
要連接到套接字 `/tmp/echo.sock`,僅需將第二行改為
~~~
var client = net.connect({path: '/tmp/echo.sock'},
~~~
### net.connect(port, [host], [connectListener])
### net.createConnection(port, [host], [connectListener])
創建一個 `host` 主機 `port` 端口的 TCP 連接。如果省略 `host` 則假定為 `'localhost'`。`connectListener` 參數會被用作 ['connect'](#) 事件的監聽器。
### net.connect(path, [connectListener])
### net.createConnection(path, [connectListener])
創建一個到路徑 `path` 的 UNIX 套接字連接。`connectListener` 參數會被用作 ['connect'](#) 事件的監聽器。
### 類: net.Server
該類用于創建一個 TCP 或 UNIX 服務器。服務器本質上是一個可監聽傳入連接的 `net.Socket`。
### server.listen(port, [host], [backlog], [callback])
在指定端口 `port` 和主機 `host` 上開始接受連接。如果省略 `host` 則服務器會接受來自所有 IPv4 地址(`INADDR_ANY`)的連接;端口為 0 則會使用分隨機分配的端口。
積壓量 `backlog` 為連接等待隊列的最大長度。實際長度由您的操作系統通過 sysctl 設置決定,比如 Linux 上的 `tcp_max_syn_backlog` 和 `somaxconn`。該參數缺省值為 511(不是 512)。
這是一個異步函數。當服務器已被綁定時會觸發 ['listening'](#) 事件。最后一個參數 `callback` 會被用作 ['listening'](#) 事件的監聽器。
有些用戶會遇到的情況是遇到 'EADDINUSE' 錯誤。這表示另一個服務器已經運行在所請求的端口上。一個處理這種情況的方法是等待一段時間再重試
~~~
server.on('error', function (e) {
if (e.code == 'EADDRINUSE') {
console.log('地址被占用,重試中...');
setTimeout(function () {
server.close();
server.listen(PORT, HOST);
}, 1000);
}
});
~~~
(注意:Node 中的所有套接字已設置了 `SO_REUSEADDR`)
### server.listen(path, [callback])
啟動一個 UNIX 套接字服務器在所給路徑 `path` 上監聽連接。
這是一個異步函數。當服務器已被綁定時會觸發 ['listening'](#) 事件。最后一個參數 `callback` 會被用作 ['listening'](#) 事件的監聽器。
### server.listen(handle, [callback])
- `handle`處理器 {Object}
- `callback`回調函數 {Function}
`handle` 變量可以被設置為server 或者 socket(任一以下劃線開頭的成員 `_handle`), 或者一個 `{fd: <n>}` 對象
這將使服務器用指定的句柄接受連接,但它假設文件描述符或者句柄已經被綁定在特定的端口或者域名套接字。
Windows 不支持監聽一個文件描述符。
這是一個異步函數。當服務器已被綁定時會觸發 ['listening'](#) 事件。最后一個參數 `callback` 會被用作 ['listening'](#) 事件的監聽器。
### server.close([callback])
用于停止服務器接受新連接,但保持已存在的連接。這是一個異步函數, 服務器將在所有的連接都結束后關閉,并且服務器發送 `'close'`事件 你可以有選擇的傳入回調函數來監聽 `'close'`事件。
### server.address()
返回操作系統報告的綁定的地址,協議族和端口。 對查找操作系統分配的地址哪個端口已被分配非常有用, 如. `{ port: 12346, family: 'IPv4', address: '127.0.0.1' }`
實例:
~~~
// 獲得隨機端口
server.listen(function() {
address = server.address();
console.log("opened server on %j", address);
});
~~~
在 `'listening'` 事件發生前請勿調用 `server.address()`。
### server.unref()
如果這是事件系統中唯一一個活動的服務器,調用 `unref` 將允許程序退出。如果服務器已被 `unref`,則再次調用 `unref` 并不會產生影響。
### server.ref()
與 `unref` 相反,如果這是僅剩的服務器,在一個之前被 `unref` 了的服務器上調用 `ref` 將不會讓程序退出(缺省行為)。如果服務器已經被 `ref`,則再次調用 `ref` 并不會產生影響。
### server.maxConnections
設置這個選項能在當服務器連接數超過數量時拒絕連接。
這個選項不推薦使用在套接字已經用 `child_process.fork()`發送給子進程。
### server.connections
這個函數已被 **廢棄**; 請用 [server.getConnections()][] 代替. 服務器的當前活動連接的數量。
當用`child_process.fork()`發送一個套接字給子進程時,它將是 `null` 。 要輪詢子進程來獲取當前活動的連接請用 `server.getConnections` 代替.
`net.Server` 是一個包含下列事件的 [EventEmitter](#) :
### server.getConnections(callback)
異步獲取服務器當前活躍的連接數. 用于套接字唄發送給子進程。
回調函數需要兩個參數 `err` 和 `count`.
### 事件: 'listening'
在服務器調用 `server.listen`綁定后觸發。
### 事件: 'connection'
- {Socket object} 連接對象
在一個新連接被創建時觸發。 `socket` 是一個`net.Socket`的實例。
### 事件: 'close'
當服務被關閉時觸發. 注意:如果當前仍有活動連接,他個事件將等到所有連接都結束后才觸發。
### 事件: 'error'
- {Error Object}
當一個錯誤發生時觸發。 `'close'` 事件將直接被下列時間調用。 請查看討論 `server.listen`的例子。
### 類: net.Socket
這個對象是一個TCP或UNIX套接字的抽象。 `net.Socket` 實例實現了一個雙工流接口。 他們可以被用戶使用在客戶端(使用 `connect()`) 或者它們可以由 Node創建,并通過 `'connection'`服務器事件傳遞給用戶。
### new net.Socket([options])
構造一個新的套接字對象。
`options` 是一個包含下列缺省值的對象:
~~~
{ fd: null
type: null
allowHalfOpen: false
}
~~~
`fd` 允許你指定一個存在的文件描述符和套接字。 `type` 指定一個優先的協議。 他可以是 `'tcp4'`, `'tcp6'`, 或 `'unix'`. 關于 `allowHalfOpen`, 參見 `createServer()` 和 `'end'` 事件。
### socket.connect(port, [host], [connectListener])
### socket.connect(path, [connectListener])
使用傳入的套接字打開一個連接 如果 `port` 和 `host` 都被傳入, 那么套接字將會被已TCP套接字打開,如果 `host` 被省略, 默認為`localhost` . 如果 `path` 被傳入, 套接字將會被已指定路徑UNIX套接字打開。
一般情況下這個函數是不需要使用, 比如用 `net.createConnection` 打開套接字. 只有在您實現了自定義套接字時候才需要。
這是一個異步函數。 當 ['connect'](#) 觸發了的套接字是established狀態 .或者在連接的時候出現了一個問題, `'connect'` 事件不會被觸發, 而 `'error'` 事件會觸發并發送異常信息。
`connectListener` 用于 ['connect'](#) 事件的監聽器
### socket.bufferSize
是一個`net.Socket` 的屬性,用于 `socket.write()` . 用于幫助用戶獲取更快的運行速度。 計算機不能一直處于大量數據被寫入狀態 —— 網絡鏈接可能會變得過慢。 Node 在內部會排隊等候數據被寫入套接字并確保傳輸連接上的數據完好。 (內部實現為:輪詢套接字的文件描述符等待它為可寫).
內部緩沖的可能后果是內存使用會增加。這個屬性表示了現在處于緩沖區等待被寫入的字符數。(字符的數目約等于要被寫入的字節數,但是緩沖區可能包含字符串,而字符串是惰性編碼的,所以確切的字節數是未知的。)
遇到數值很大或者增長很快的`bufferSize`的時候,用戶應該嘗試用`pause()`和`resume()`來控制數據流。
### socket.setEncoding([encoding])
設置套接字的編碼為一個可讀流. 更多信息請查看 [stream.setEncoding()](#)
### socket.write(data, [encoding], [callback])
在套接字上發送數據。第二參數指明了使用字符串時的編碼方式-默認為UTF8編碼。
如果所有數據被成功刷新到內核緩沖區,則返回`true`。如果所有或部分數據在用戶內存里還處于隊列中,則返回`false`。當緩沖區再次被釋放時,`'drain'`事件會被分發。
當數據最終被完整寫入時,可選的`callback`參數會被執行 - 但不一定是馬上執行。
### socket.end([data], [encoding])
半關閉套接字 如., 它發送一個 FIN 包 .可能服務器仍在發送數據。
如果 `data`被傳入, 等同于調用 `socket.write(data, encoding)` 然后調用 `socket.end()`.
### socket.destroy()
確保沒有I/O活動在這個套接字。 只有在錯誤發生情況下才需要(處理錯誤等等)。
### socket.pause()
暫停讀取數據。 `'data'` 事件不會被觸發。 對于控制上傳非常有用。
### socket.resume()
在調用 `pause()`后恢復讀操作。
### socket.setTimeout(timeout, [callback])
如果套接字超過`timeout`毫秒處于閑置狀態,則將套接字設為超時。默認情況下`net.Socket`不存在超時。
當一個閑置超時被觸發時,套接字會接收到一個`'timeout'`事件,但是連接將不會被斷開。用戶必須手動`end()`或`destroy()`這個套接字。
如果`timeout`為0,那么現有的閑置超時會被禁用。
可選的`callback`參數將會被添加成為`'timeout'`事件的一次性監聽器。
### socket.setNoDelay([noDelay])
禁用納格(Nagle)算法。默認情況下TCP連接使用納格算法,這些連接在發送數據之前對數據進行緩沖處理。 將`noDelay`設成`true`會在每次`socket.write()`被調用時立刻發送數據。`noDelay`默認為`true`。
### socket.setKeepAlive([enable], [initialDelay])
禁用/啟用長連接功能,并在第一個在閑置套接字上的長連接probe被發送之前,可選地設定初始延時。`enable`默認為`false`。
設定`initialDelay` (毫秒),來設定在收到的最后一個數據包和第一個長連接probe之間的延時。將initialDelay設成0會讓值保持不變(默認值或之前所設的值)。默認為`0`。
### socket.address()
返回 socket 綁定的IP地址, 協議類型 (family name) 以及 端口號 (port). 具體是一個包含三個屬性的對象, 形如 `{ port: 12346, family: 'IPv4', address: '127.0.0.1' }`
### socket.unref()
如果這是事件系統中唯一一個活動的套接字,調用 `unref` 將允許程序退出。如果套接字已被 `unref`,則再次調用 `unref` 并不會產生影響。
### socket.ref()
與 `unref` 相反,如果這是僅剩的套接字,在一個之前被 `unref` 了的套接字上調用 `ref` 將*不會*讓程序退出(缺省行為)。如果一個套接字已經被 `ref`,則再次調用 `ref` 并不會產生影響。
### socket.remoteAddress
遠程IP地址的字符串表示。例如,`'74.125.127.100'`或 `'2001:4860:a005::68'`。
### socket.remotePort
遠程端口的數值表示。例如,`80` 或 `21`。
### socket.localAddress
遠程客戶端正在連接的本地IP地址的字符串表示。例如,如果你在監聽`'0.0.0.0'`而客戶端連接在`'192.168.1.1'`,這個值就會是 `'192.168.1.1'`。
### socket.localPort
本地端口的數值表示。比如`80` 或 `21`。
### socket.bytesRead
所接收的字節數。
### socket.bytesWritten
所發送的字節數。
`net.Socket`實例是帶有以下事件的[EventEmitter](#)對象:
### 事件: 'lookup'
這個事件在解析主機名之后,連接主機之前被分發。對UNIX套接字不適用。
- `err` {Error | Null} 錯誤對象。見[dns.lookup()][]。
- `address` {String} IP地址。
- `family` {String | Null} 得知類型。見[dns.lookup()][]。
### 事件: 'connect'
該事件在一個套接字連接成功建立后被分發。見`connect()`。
### 事件: 'data'
- {Buffer object}
當收到數據時被分發。`data`參數會是一個`Buffer`或`String`對象。數據的編碼方式由`socket.setEncoding()`設定。 (詳見 [可讀流][] 章節)
請注意,如果一個`Socket`對象分發一個`'data'`事件時沒有任何監聽器存在,則 **數據會丟失**。
### 事件: 'end'
當套接字的另一端發送FIN包時,該事件被分發。
默認情況下 (`allowHalfOpen == false`),當套接字完成待寫入隊列中的任務時,它會destroy文件描述符。然而,如果把`allowHalfOpen`設成`true`,那么套接字將不會從它這邊自動調用`end()`,使得用戶可以隨意寫入數據,但同時使得用戶自己需要調用`end()`。
### 事件: 'timeout'
當套接字因為非活動狀態而超時時該事件被分發。這只是用來表明套接字處于空閑狀態。用戶必須手動關閉這個連接。
參閱:`socket.setTimeout()`
### 事件: 'drain'
當寫入緩沖被清空時產生。可被用于控制上傳流量。
參閱:`socket.write()` 的返回值
### 事件: 'error'
- {Error object}
當一個錯誤發生時產生。`'close'` 事件會緊接著該事件被觸發。
### 事件: 'close'
- `had_error` {Boolean} 如果套接字發生了傳輸錯誤則此字段為true
當套接字完全關閉時該事件被分發。參數`had_error`是一個布爾值,表示了套接字是否因為一個傳輸錯誤而被關閉。
### net.isIP(input)
測試 input 是否 IP 地址。無效字符串返回 0;IP 版本 4 地址返回 4;IP 版本 6 地址返回 6。
### net.isIPv4(input)
如果 input 為版本 4 地址則返回 true,否則返回 false。
### net.isIPv6(input)
如果 input 為版本 6 地址則返回 true,否則返回 false。