nodeJS之TCP模塊net

前面的話

  TCP服務在網絡應用中十分常見,目前大多數的應用都是基於TCP搭建而成的。net模塊提供了一個異步網絡包裝器,用於TCP網絡編程,它包含了建立服務器和客戶端的方法。本文將詳細介紹nodeJS中的net模塊node

 

IP測試

【net.isIP(input)】linux

  測試是否輸入的爲 IP 地址。字符串無效時返回 0。 IPV4 狀況下返回 4, IPV6狀況下返回 6算法

var net = require('net');
console.log(net.isIP('1.1.1.1'));//4
console.log(net.isIP('1.1'));//0
console.log(net.isIP('AD80::ABAA:0000:00C2:0002'));//6

【net.isIPv4(input)】編程

  若是輸入的地址爲 IPV4, 返回 true,不然返回 false數組

var net = require('net');
console.log(net.isIPv4('1.1.1.1'));//true
console.log(net.isIPv4('1.1'));//false

【net.isIPv6(input)】緩存

  若是輸入的地址爲 IPV6, 返回 true,不然返回 false服務器

var net = require('net');
console.log(net.isIPv6('1.1.1.1'));//true
console.log(net.isIPv6('AD80::ABAA:0000:00C2:0002'));//true

 

服務器

【net.createServer([options][, connectionListener])】網絡

  建立一個 TCP 服務器,參數以下異步

options
    allowHalfOpen: false(默認),若是爲true,當另外一端socket發送FIN包時socket不會自動發送FIN包。socket變爲不可讀但可寫(半關閉)
    pauseOnConnect: false(默認),若是爲true,當鏈接到來的時候相關聯的socket將會暫停。它容許在初始進程不讀取數據狀況下,讓鏈接在進程間傳遞。調用resume()從暫停的socket裏讀取數據
connectionListener 自動給 'connection' 事件建立監聽器
var server = net.createServer(function() {

});

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

  開始接受指定端口port和主機host的鏈接。若是忽略主機host,服務器將會接受任何IPv4地址(INADDR_ANY)的直接鏈接。端口爲0,則會分配一個隨機端口

  積壓量(Backlog)爲鏈接等待隊列的最大長度。實際長度由操做系統經過sysctl設定,好比linux上的tcp_max_syn_backlog和somaxconn。這個參數默認值是511

  當服務器被綁定時會觸發'listening'事件。最後一個參數callback將會做爲'listening'事件的監聽器

  有些用戶會遇到EADDRINUSE錯誤,它表示另一個服務器已經運行在所請求的端口上。處理這個狀況的辦法是等一段時間後再重試

server.listen(6000);

【server.close([callback])】

  服務器中止接收新的鏈接,保持現有鏈接。當全部鏈接結束的時候服務器會關閉,並會觸發'close'事件。你能夠傳一個回調函數來監聽'close'事件。若是存在,將會調用回調函數,錯誤(若是有)做爲惟一參數

【server.address()】

  操做系統返回綁定的地址、協議族名和服務器端口。查找哪一個端口已經被系統綁定時,很是有用

  [注意]在 'listening' 事件觸發前,不要調用 server.address()

server.listen(function() {
    //{ address: '::', family: 'IPv6', port: 53806 }
    console.log(server.address());
});

【server.maxConnections】

  設置這個選項後,當服務器鏈接數超過數量時拒絕新鏈接

  一旦已經用 child_process.fork() 方法將 socket 發送給子進程, 就不推薦使用這個選項

【server.getConnections(callback)】

  異步獲取服務器當前活躍鏈接的數量。當 socket 發送給子進程後纔有效;

  回調函數有 2 個參數 err 和 count

server.getConnections(function(err,count){
    console.log(count);//0
})

【事件listening】

  當服務器調用 server.listen 綁定後會觸發

【事件connection】

{Socket object} 鏈接對象

  當新鏈接建立後會被觸發。socket 是 net.Socket實例

【事件close】

  服務器關閉時會觸發

  [注意]若是存在鏈接,這個事件不會被觸發直到全部的鏈接關閉

【事件error】

  發生錯誤時觸發

 

客戶端

【net.connect(options[, connectionListener])】

【net.createConnection(options[, connectionListener])】

  connect()的別名是createConnection()方法

  該方法返回一個新的 'net.Socket',並鏈接到指定的地址和端口。當 socket 創建的時候,將會觸發 'connect' 事件。和'net.Socket'有相同的方法

  對於 TCP sockets,參數options以下

port: 客戶端鏈接到 Port 的端口(必須)
host: 客戶端要鏈接到得主機。默認 'localhost'
localAddress: 網絡鏈接綁定的本地接口
localPort: 網絡鏈接綁定的本地端口
family : IP 棧版本。默認 4

  對於本地域socket,參數options以下

path: 客戶端鏈接到得路徑(必須)
var client = net.connect({port: 5000}, function() {});

 

Socket

【new net.Socket([options])】

  構造一個新的 socket 對象

  options 對象有如下默認值:

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

  參數fd容許指定一個存在的文件描述符。將readable和(或)writable設爲true,容許在這個socket上讀或寫(僅在參數fd有效時)

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

【socket.connect(path[, connectListener])】

  使用傳入的socket打開一個鏈接。若是指定了端口port和主機host,TCP socket將打開socket。若是忽略參數host,則默認爲localhost。若是指定了path,socket將會被指定路徑的unix socket 打開

  參數 connectListener 將會做爲監聽器添加到 'connect' 事件

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

  在socket上發送數據。第二個參數指定了字符串的編碼,默認是UTF8編碼

  若是全部數據成功刷新到內核緩衝區,返回true。若是數據所有或部分在用戶內存裏,返回false。當緩衝區爲空的時候會觸發'drain'

  當數據最終被完整寫入的的時候,可選的callback參數會被執行,但不必定會立刻執行

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

  半關閉socket。例如,它發送一個FIN包。可能服務器仍在發送數據。

  若是參數data不爲空,等同於調用socket.write(data,encoding)後再調用socket.end()

【socket.destroy()】

  確保沒有 I/O 活動在這個套接字上。只有在錯誤發生狀況下才須要

【socket.pause()】

  暫停讀取數據。就是說,不會再觸發 data 事件。對於控制上傳很是有用

【socket.resume()】

  調用 pause() 後想恢復讀取數據

【socket.setTimeout(timeout[, callback])】

  socket 閒置時間超過 timeout 毫秒後 ,將 socket 設置爲超時。觸發空閒超時事件時,socket 將會收到 'timeout'事件,可是鏈接不會被斷開。用戶必須手動調用 end() 或 destroy() 這個socket。

  若是 timeout = 0, 那麼現有的閒置超時會被禁用。可選的 callback 參數將會被添加成爲 'timeout' 事件的一次性監聽器

【socket.setNoDelay([noDelay])】

  禁用納格(Nagle)算法。默認狀況下 TCP 鏈接使用納格算法,在發送前他們會緩衝數據。將 noDelay 設置爲 true 將會在調用 socket.write() 時當即發送數據。noDelay 默認值爲 true

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

  禁用/啓用長鏈接功能,在發送第一個在閒置socket上的長鏈接probe以前,可選地設定初始延時。默認false

  設定initialDelay(毫秒),來設定收到的最後一個數據包和第一個長鏈接probe之間的延時。將 initialDelay 設爲0,將會保留默認(或者以前)的值。默認值爲0

【socket.address()】

  操做系統返回綁定的地址,協議族名和服務器端口。返回的對象有 3 個屬性,好比{ port: 12346, family: 'IPv4', address: '127.0.0.1' }

【socket.remoteAddress】

  遠程的 IP 地址字符串

【socket.remoteFamily】

  遠程IP協議族字符串

【socket.remotePort】

  遠程端口,數字表示

【socket.localAddress】

  遠程客戶端正在鏈接的本地IP地址,字符串表示

【socket.localPort】

  本地端口地址,數字表示

【socket.bytesRead】

  接收的字節數

【socket.bytesWritten】

  發送的字節數

【事件lookup】

  在解析域名後,但在鏈接前,觸發這個事件。對 UNIX sokcet 不適用

err {Error | Null} 錯誤對象
address {String} IP 地址。
family {String | Null} 地址類型

【事件connect】

  當成功創建 socket 鏈接時觸發、

【事件data】

{Buffer object}

  當接收到數據時觸發。參數 data 能夠是 Buffer 或 String

  當 Socket 觸發一個 'data' 事件時,若是沒有監聽器,數據將會丟失

【事件end】

  當 socket 另外一端發送 FIN 包時,觸發該事件

【事件timeout】

  當 socket 空閒超時時觸發,僅是代表 socket 已經空閒。用戶必須手動關閉鏈接

【事件drain】

  當寫緩存爲空得時候觸發。可用來控制上傳

【事件error】

  錯誤發生時觸發

【事件close】

had_error {Boolean} 若是 socket 傳輸錯誤,爲 true

  當 socket 徹底關閉時觸發。參數 had_error 是 boolean,它表示是否由於傳輸錯誤致使 socket 關閉

 

簡易服務器

【服務器】

//server.js
var net = require('net') ;
var server = net.createServer(function(socket) { 
    socket.write("Hi!\n");
    socket.on("data", function(data) {
      console.log(data.toString());
    });
    socket.on("end", function() {
      console.log('有客戶機下線了!!!');
    });
    socket.on('error', function() {
      console.log('發生意外錯誤!!!');
    });
}) ;
server.listen(8080) ;

【客戶機】

//client.js
var net = require('net') ;
var client = net.connect({port: 8080},function(){
    client.name = '客戶機1';
    client.write(client.name + ' 上線了!\n');
    client.end(client.name + ' 下線了!\n');
    client.on("data", function(data) {
        console.log(data.toString());
    });
});

 

簡易聊天室

【服務器】

//chatServer.js
var net = require('net');
var i = 0;
//保存客戶機
var clientList = [];
var server = net.createServer(function(socket) {
    socket.name = '用戶' + (++i);
    socket.write('【聊天室提示】歡迎' + socket.name + '\n');
    //更新客戶機數組
    clientList.push(socket); 
    function showClients(){
        console.log('【當前在線用戶】:');
        for(var i=0;i<clientList.length;i++) { 
            console.log(clientList[i].name);
        }        
    }
    showClients();
    socket.on("data", function(data) {
        //把當前鏈接的客戶機的信息轉發到其餘客戶機  
        for(var i=0;i<clientList.length;i++) { 
            if(socket !== clientList[i]) {      
                clientList[i].write('【' + socket.name + '】:' + data);   
            }  
        }
    });
    socket.on("close", function() {
        //當前客戶機下線時,將其從客戶機數組中移除
        clientList.splice(clientList.indexOf(socket), 1);
        showClients();
    });
    socket.on('error', function(err) {
        console.log(socket.name + '退出');
    });
});
server.listen(8080) ;

【客戶機】

//chatClient.js
var net = require('net');
process.stdin.resume();
process.stdin.setEncoding('utf8');
var client = net.connect({port: 8080},function(){
    console.log('【本機提示】登陸到聊天室');
    process.stdin.on('data',function(data){
        client.write(data);
    })
    client.on("data", function(data) {
        console.log(data.toString());
    });
    client.on('end', function() {
        console.log('【本機提示】退出聊天室');
        process.exit();
    });
    client.on('error', function() {
        console.log('【本機提示】聊天室異常');
        process.exit();
    });
});

相關文章
相關標籤/搜索