中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Node.js之網絡通訊模塊實現淺析

發布時間:2020-09-22 18:20:57 來源:腳本之家 閱讀:130 作者:C小K 欄目:web開發

前言

想必我們在用Node.js用的最多的應該是創建http服務,所以對于每個Web開發工程師而言,Node.js的網絡相關模塊學習是必不可少。

Node.js的網絡模塊架構

在Node.js的模塊里面,與網絡相關的模塊有Net、DNS、HTTP、TLS/SSL、HTTPS、UDP/Datagram,除此之外,還有v8底層相關的網絡模塊有tcp_wrap.ccudp_wrap.ccpipe_wrap.ccstream_wrap.cc等等,在Javascript層以及C++層之間通過process.binding進行橋接相互通信。

Node.js之網絡通訊模塊實現淺析

Net模塊

Net模塊提供了一些用于底層的網絡通信接口,包括創建服務器以及客戶端,其中HTTP模塊也是基于Net模型的上層封裝,在Net模塊里面主要提供net.Server以及net.Socket

創建TCP服務端

創建一個TCP服務器,可以通過使用構造函數new net.Server或者使用工廠方法net.createServer,這兩個方法都會返回一個net.Server類,可接收兩個可選參數。

var net = require('net');

var server = net.createServer(function(socket){

  socket
    .on('data',function(data){
      console.log('socket data',data.toString());
      socket.write( data.toString() );
    })
    .on('end',function(){
      console.log('socket end')
    })
    .on('error',function(error){
      console.log('socket error',error);
    });
});

server.listen(56200,function(){
  console.log('server run at ',server.address());
});

server.on('error',function(err){
  throw err;
});
// 執行后:server run at { address: '::', family: 'IPv6', port: 56200 }

在listen監聽的時候沒有指定端口的話會自動隨意監聽一個端口,創建完成一個TCP服務器后,使用tenlent 0.0.0.0 56200,鏈接后可與服務器進行數據通信。通過createServer實例化一個服務后,服務會去監聽客戶端請求,與客戶端建立了鏈接之后會在回調里面拋出建鏈的net.Socket對象。

創建TCP客戶端

創建一個TCP客戶端鏈接可以使用構造函數new net.Socket或者其工廠方法net.createConnection,創建成功后都會返回一個net.Socket實例。

var net = require('net');

var client = net.createConnection({port:56200,host:'localhost'});

client.on('connect',function(){
  console.log('client connect');
});

client.on('data',function(data){
  console.log('client data',toString());
});

client.on('error',function(error){
  throw error;
});

client.on('close',function(){
  console.log('client close');
});

Socket

socket是啥這里就不做詳細的闡述了,下面主要了解下net.Socket這個構造體主要有提供一些什么方法、監聽事件的使用。

相關事件

  1. connect : 當客戶端與服務端成功建立鏈接之后觸發,如果鏈接不上服務器直接拋出error事件錯誤然后退出node進程。
  2. data : 當客戶端收到服務器傳送過來的數據或者是客戶端傳送給服務器的數據的時候觸發回調。
  3. end : 當另外一側發送FIN包斷開的時候觸發,默認情況下面 (allowHalfOpen == false)socket會自我銷毀(如果寫入待處理隊列里面還沒正式響應回包),但是我們可以設置allowHalfOpen參數為true,這樣可以繼續往該socket里面寫數據,但是我們需要自己去調用 end 方法去消耗這個socket,不然可能會造成句柄泄漏。
  4. close : 鏈接斷開的時候觸發,但是如果在傳輸的過程中有錯誤的話這里會在回調函數里面拋出 error。
  5. timeout : 當socket超時空閑的時候觸發,如果要在隊列里面銷毀需要手動去調close方法。
  6. lookup : 域名解析完成的時候觸發。
  7. drain : 寫完緩存的時候觸發,可使用在上傳大小限制中。

相關方法

  1. write() : 服務端給客戶端發送數據或者是客戶端給服務端發送數據。
  2. address() : 獲取服務綁定的socket的IP地址,返回對象有三個屬性,分別為端口、host以
  3. 及IPvX版本。
  4. end() : 半關閉socket,會發送一個FIN包,服務器仍然可能發送一些數據,也可以這樣調用socket.end(data,encoding)。
  5. pause() : 暫停讀取數據,可以用作對數據上傳限制。
  6. resume() : 繼續數據讀取。
  7. setEncoding() : 設置數據流的獲取格式。
  8. setKeepAlive() : 允許/禁止keep-alive功能。
  9. setNoDelay() : 禁止Nagele算法,TCP鏈接默認使用Nagle算法,它們在發送之前數據會被緩存。這是為true的話在每次socket.write()的時候會立即發送數據,默認為true。
  10. setTimeout() : 當一個空閑的socket在多少秒后不活躍會被接受到timeout事件,但是該socket不會停止銷毀,需要手動調用end()或者destroy()。表示禁止空閑超時。

相關屬性

  1. bufferSize : 當前緩存的等待被發送的字符串的數量。
  2. bytesRead : 收到的字節的數量。
  3. bytesWritten : 發送的字節的數量
  4. destroyed : 標識鏈接是否已經被破壞,一旦被破環,就不用使用該鏈接來傳輸數據。
  5. localAddress : 遠程客戶端鏈接本地地址的host。如果我們監聽服務的host是0.0.0.0,而客戶端鏈接的是'192.168.1.1',最后的值是后者。
  6. localPort : 本地的端口。
  7. remoteAddress : 客戶端IP,如果socket已經是destryed的話,該值為undefined
  8. remoteFamily : 客戶端是IPvX

回包異常處理

服務器從客戶端接受到需要處理的數據后進入處理環節,再業務邏輯處理完成之前如果socket以外斷開的話,待服務器再給客戶端回報的時候會直接響應error事件并報錯Error : This socket has benn ended by the other part,所以在回報之前服務端需要先判斷該socket是否被銷毀,如果沒有被銷毀則回包,如果已經斷開則銷毀:

var net = require('net');
var biz = require('./biz');
var server = net.createServer(function(socket){

  socket
    .on('data',function(data){
      biz.do(data)
        .then(function(){
          if( !socket.destroyed ) {
            socket.write( data.toString() );
          } else {
            // do some report
            socket.destry();
          }
        })
        .catch(function(){
          !socket.destroyed && socket.end('server handler error');
        });
      
    })
    .on('end',function(){
      console.log('socket end')
    })
    .on('error',function(error){
      console.log('socket error',error);
    });
});

server.listen(56200,function(){
  console.log('server run at ',server.address());
});

server.on('error',function(err){
  throw err;
});

限制客戶端數據大小

對請求大小限制是服務安全里面比不可少的一個環節,服務端不能無限大小的去接受客戶端發送過來的所有數據,而限制大小就是第一道門檻。

var net = require('net');
var MAX_REQUEST_BYTES = 2 * 1024 * 1024; // 2M
var server = net.createServer(function(socket){

  socket
    .on('data',function(data){
      
      if(data.bytesRead > MAX_REQUEST_BYTES) {
        socket.pause();
        socket.end('data is too big, forbidden');
        // do some report
      }
    })
    .on('end',function(){
      console.log('socket end')
    })
    .on('error',function(error){
      console.log('socket error',error);
    });
});

server.listen(56200,function(){
  console.log('server run at ',server.address());
});

server.on('error',function(err){
  throw err;
});

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

姜堰市| 东乡县| 元氏县| 陆河县| 墨脱县| 吴旗县| 清远市| 抚松县| 阿克苏市| 揭东县| 绍兴县| 景谷| 芜湖市| 微博| 平和县| 商洛市| 光泽县| 咸丰县| 温宿县| 娄烦县| 林州市| 资源县| 开远市| 绥江县| 临夏市| 渭南市| 通渭县| 绵竹市| 合山市| 湖南省| 绥芬河市| 溧阳市| 岫岩| 思茅市| 沙坪坝区| 兴安县| 闽清县| 沁水县| 留坝县| 泰州市| 靖边县|