最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Node.js net模塊的使用示例

 更新時間:2025年02月27日 10:43:18   作者:神秘代碼行者  
本文主要介紹了Node.js net模塊的使用示例,net模塊支持TCP通信,處理TCP連接和數(shù)據(jù)傳輸,具有一定的參考價值,感興趣的可以了解一下

簡介

Node.js 的 net 模塊提供了用于實(shí)現(xiàn) TCP 服務(wù)器和客戶端的異步網(wǎng)絡(luò) API。它是 Node.js 網(wǎng)絡(luò)功能的核心,為上層模塊如 HTTP、HTTPS 等提供了基礎(chǔ)支持。本教程將全面介紹 net 模塊的使用方法和最佳實(shí)踐。

引入 net 模塊

const net = require('net');

核心概念

TCP (傳輸控制協(xié)議)

TCP 是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。net 模塊主要處理 TCP 通信。

Socket

Socket 是網(wǎng)絡(luò)通信的端點(diǎn),在 Node.js 中表示為 net.Socket 類的實(shí)例。它可以是服務(wù)器與客戶端之間建立的連接,也可以是客戶端主動創(chuàng)建的連接。

服務(wù)器

服務(wù)器使用 net.Server 類創(chuàng)建,負(fù)責(zé)監(jiān)聽連接并處理客戶端請求。

TCP 服務(wù)器創(chuàng)建

基本服務(wù)器

const net = require('net');

// 創(chuàng)建服務(wù)器
const server = net.createServer((socket) => {
  console.log('客戶端已連接');
  
  // 接收數(shù)據(jù)
  socket.on('data', (data) => {
    console.log(`接收到數(shù)據(jù): ${data}`);
    // 發(fā)送響應(yīng)
    socket.write('服務(wù)器已收到你的消息');
  });
  
  // 連接關(guān)閉
  socket.on('end', () => {
    console.log('客戶端已斷開連接');
  });
  
  // 處理錯誤
  socket.on('error', (err) => {
    console.error('連接錯誤:', err);
  });
});

// 監(jiān)聽端口
server.listen(3000, () => {
  console.log('服務(wù)器啟動成功,監(jiān)聽端口 3000');
});

服務(wù)器配置選項(xiàng)

創(chuàng)建服務(wù)器時可以傳遞配置選項(xiàng):

const server = net.createServer({
  allowHalfOpen: false, // 當(dāng)另一端發(fā)送 FIN 包時自動發(fā)送 FIN (默認(rèn))
  pauseOnConnect: false // 是否在連接時暫停套接字 (默認(rèn))
});

服務(wù)器事件

net.Server 類繼承自 EventEmitter,支持以下主要事件:

  • listening: 服務(wù)器開始監(jiān)聽連接時觸發(fā)
  • connection: 新客戶端連接建立時觸發(fā)
  • error: 發(fā)生錯誤時觸發(fā)
  • close: 服務(wù)器關(guān)閉時觸發(fā)
server.on('listening', () => {
  console.log('服務(wù)器開始監(jiān)聽連接');
});

server.on('connection', (socket) => {
  console.log('新客戶端連接');
});

server.on('error', (err) => {
  console.error('服務(wù)器錯誤:', err);
});

server.on('close', () => {
  console.log('服務(wù)器已關(guān)閉');
});

TCP 客戶端創(chuàng)建

基本客戶端

const net = require('net');

// 創(chuàng)建連接
const client = net.createConnection({ 
  host: 'localhost',
  port: 3000 
}, () => {
  console.log('已連接到服務(wù)器');
  // 發(fā)送數(shù)據(jù)
  client.write('你好,服務(wù)器');
});

// 接收數(shù)據(jù)
client.on('data', (data) => {
  console.log(`接收到服務(wù)器響應(yīng): ${data}`);
  // 關(guān)閉連接
  client.end();
});

// 連接結(jié)束
client.on('end', () => {
  console.log('已斷開與服務(wù)器的連接');
});

// 錯誤處理
client.on('error', (err) => {
  console.error('連接錯誤:', err);
});

客戶端配置選項(xiàng)

創(chuàng)建客戶端連接時可以傳遞多種配置選項(xiàng):

const client = net.createConnection({
  host: 'localhost', // 主機(jī)名
  port: 3000,        // 端口號
  localAddress: '192.168.1.100', // 本地接口
  family: 4,         // IP 版本 (4 或 6)
  timeout: 5000      // 連接超時(毫秒)
});

Socket 對象

net.Socket 是 TCP 連接的抽象,具有流(Duplex Stream)的特性,既可讀又可寫。

創(chuàng)建 Socket

除了服務(wù)器自動創(chuàng)建外,也可以手動創(chuàng)建:

const socket = new net.Socket();
socket.connect(3000, 'localhost', () => {
  console.log('連接成功');
});

Socket 屬性

  • socket.remoteAddress: 遠(yuǎn)程 IP 地址
  • socket.remotePort: 遠(yuǎn)程端口
  • socket.localAddress: 本地 IP 地址
  • socket.localPort: 本地端口
  • socket.bytesRead: 接收的字節(jié)數(shù)
  • socket.bytesWritten: 發(fā)送的字節(jié)數(shù)
socket.on('connect', () => {
  console.log(`連接到 ${socket.remoteAddress}:${socket.remotePort}`);
  console.log(`本地端口: ${socket.localPort}`);
});

Socket 方法

  • socket.write(data[, encoding][, callback]): 發(fā)送數(shù)據(jù)
  • socket.end([data][, encoding][, callback]): 結(jié)束連接
  • socket.destroy([error]): 強(qiáng)制關(guān)閉連接
  • socket.pause(): 暫停數(shù)據(jù)讀取
  • socket.resume(): 恢復(fù)數(shù)據(jù)讀取
  • socket.setKeepAlive([enable][, initialDelay]): 設(shè)置 keepalive
  • socket.setNoDelay([noDelay]): 禁用 Nagle 算法

事件處理

服務(wù)器事件

server.on('listening', () => {
  const address = server.address();
  console.log(`服務(wù)器監(jiān)聽 ${address.address}:${address.port}`);
});

server.on('error', (err) => {
  if (err.code === 'EADDRINUSE') {
    console.error('端口已被占用');
  }
});

Socket 事件

  • connect: 成功建立連接時觸發(fā)
  • data: 接收到數(shù)據(jù)時觸發(fā)
  • end: 對方結(jié)束發(fā)送數(shù)據(jù)時觸發(fā)
  • timeout: 連接超時時觸發(fā)
  • error: 發(fā)生錯誤時觸發(fā)
  • close: 連接完全關(guān)閉時觸發(fā)
socket.on('data', (data) => {
  console.log(`接收到數(shù)據(jù): ${data.toString()}`);
});

socket.on('timeout', () => {
  console.log('連接超時');
  socket.end();
});

socket.on('close', (hadError) => {
  console.log(`連接關(guān)閉${hadError ? ',發(fā)生錯誤' : ''}`);
});

數(shù)據(jù)傳輸

發(fā)送數(shù)據(jù)

// 發(fā)送字符串
socket.write('Hello', 'utf8');

// 發(fā)送 Buffer
const buffer = Buffer.from([0x68, 0x65, 0x6c, 0x6c, 0x6f]);
socket.write(buffer);

// 使用回調(diào)確認(rèn)數(shù)據(jù)已被發(fā)送
socket.write('World', () => {
  console.log('數(shù)據(jù)已發(fā)送');
});

接收數(shù)據(jù)

let chunks = [];

socket.on('data', (chunk) => {
  chunks.push(chunk);
});

socket.on('end', () => {
  const data = Buffer.concat(chunks).toString();
  console.log(`完整數(shù)據(jù): ${data}`);
});

處理二進(jìn)制數(shù)據(jù)

socket.on('data', (chunk) => {
  // 假設(shè)前兩個字節(jié)表示消息長度
  const messageLength = chunk.readUInt16BE(0);
  const message = chunk.slice(2, 2 + messageLength);
  console.log(`消息內(nèi)容: ${message.toString()}`);
});

高級特性

IPC (進(jìn)程間通信)

除了 TCP 通信,net 模塊也支持通過 Unix 域套接字或命名管道進(jìn)行進(jìn)程間通信:

// 服務(wù)器
const server = net.createServer().listen('/tmp/echo.sock');

// 客戶端
const client = net.createConnection({ path: '/tmp/echo.sock' });

多連接管理

實(shí)際應(yīng)用中,服務(wù)器通常需要管理多個連接:

const connections = new Map();

server.on('connection', (socket) => {
  const id = `${socket.remoteAddress}:${socket.remotePort}`;
  connections.set(id, socket);
  
  socket.on('close', () => {
    connections.delete(id);
    console.log(`客戶端 ${id} 已斷開,當(dāng)前連接數(shù): ${connections.size}`);
  });
});

// 向所有客戶端廣播消息
function broadcast(message) {
  for (const socket of connections.values()) {
    socket.write(message);
  }
}

重連機(jī)制

客戶端斷線重連示例:

function createClient() {
  const client = net.createConnection({ port: 3000 });
  
  client.on('error', (err) => {
    console.error('連接錯誤:', err);
  });
  
  client.on('close', () => {
    console.log('連接關(guān)閉,嘗試重連...');
    setTimeout(() => {
      createClient();
    }, 3000); // 3秒后重連
  });
  
  return client;
}

const client = createClient();

實(shí)際應(yīng)用案例

簡單聊天服務(wù)器

const net = require('net');
const clients = [];

const server = net.createServer((socket) => {
  // 為新連接分配昵稱
  socket.name = `用戶${clients.length + 1}`;
  
  // 廣播新用戶連接消息
  const message = `${socket.name} 已加入聊天室`;
  broadcast(message, socket);
  
  // 添加到客戶端列表
  clients.push(socket);
  
  // 歡迎消息
  socket.write(`歡迎來到聊天室,${socket.name}!\n`);
  
  // 接收消息
  socket.on('data', (data) => {
    broadcast(`${socket.name}: ${data}`, socket);
  });
  
  // 斷開連接
  socket.on('end', () => {
    clients.splice(clients.indexOf(socket), 1);
    broadcast(`${socket.name} 已離開聊天室`, socket);
  });
  
  // 處理錯誤
  socket.on('error', (err) => {
    console.error(`${socket.name} 發(fā)生錯誤:`, err);
  });
});

// 廣播消息給所有客戶端
function broadcast(message, sender) {
  clients.forEach((client) => {
    // 不發(fā)送給消息發(fā)送者
    if (client !== sender) {
      client.write(message);
    }
  });
  console.log(message);
}

server.listen(3000, () => {
  console.log('聊天服務(wù)器已啟動,監(jiān)聽端口 3000');
});

簡單的 HTTP 服務(wù)器

使用 net 模塊實(shí)現(xiàn)基礎(chǔ) HTTP 服務(wù)器:

const net = require('net');

const server = net.createServer((socket) => {
  socket.on('data', (data) => {
    const request = data.toString();
    console.log('收到請求:', request);
    
    // 簡單的 HTTP 響應(yīng)
    const response = [
      'HTTP/1.1 200 OK',
      'Content-Type: text/html',
      'Connection: close',
      '',
      '<html><body><h1>Hello from Node.js net module</h1></body></html>'
    ].join('\r\n');
    
    socket.write(response);
    socket.end();
  });
  
  socket.on('error', (err) => {
    console.error('Socket 錯誤:', err);
  });
});

server.listen(8080, () => {
  console.log('HTTP 服務(wù)器運(yùn)行在 http://localhost:8080/');
});

性能優(yōu)化

使用 Buffer 池

對于高性能應(yīng)用,可以使用 Buffer 池避免頻繁創(chuàng)建新 Buffer:

const bufferPool = Buffer.allocUnsafe(1024 * 100); // 100KB 池
let offset = 0;

function allocateBuffer(size) {
  if (offset + size > bufferPool.length) {
    offset = 0; // 重置偏移
  }
  
  const buffer = bufferPool.slice(offset, offset + size);
  offset += size;
  return buffer;
}

// 使用預(yù)分配的 buffer 發(fā)送數(shù)據(jù)
const dataToSend = "Hello";
const buffer = allocateBuffer(dataToSend.length);
buffer.write(dataToSend);
socket.write(buffer);

避免小包發(fā)送

合并小數(shù)據(jù)包可以提高網(wǎng)絡(luò)效率:

const queue = [];
let isFlushing = false;

function queueData(socket, data) {
  queue.push(data);
  
  if (!isFlushing) {
    isFlushing = true;
    process.nextTick(flushQueue, socket);
  }
}

function flushQueue(socket) {
  if (queue.length > 0) {
    const data = Buffer.concat(queue);
    queue.length = 0;
    socket.write(data);
  }
  isFlushing = false;
}

調(diào)整 Socket 參數(shù)

針對不同場景優(yōu)化 Socket 設(shè)置:

// 低延遲應(yīng)用 (禁用 Nagle 算法)
socket.setNoDelay(true);

// 長連接應(yīng)用
socket.setKeepAlive(true, 60000); // 60秒

// 設(shè)置超時
socket.setTimeout(30000); // 30秒
socket.on('timeout', () => {
  console.log('連接超時');
  socket.end();
});

常見問題解答

Q: 如何處理 EADDRINUSE 錯誤?

A: 這個錯誤表示端口已被占用,可以通過以下方式處理:

server.on('error', (err) => {
  if (err.code === 'EADDRINUSE') {
    console.log('端口已被占用,嘗試其他端口...');
    server.close();
    server.listen(port + 1);
  }
});

Q: 如何實(shí)現(xiàn)心跳機(jī)制?

A: 通過定時發(fā)送心跳包確保連接活躍:

// 服務(wù)端心跳檢測
const clients = new Map();

server.on('connection', (socket) => {
  const id = `${socket.remoteAddress}:${socket.remotePort}`;
  clients.set(id, { socket, lastHeartbeat: Date.now() });
  
  socket.on('data', (data) => {
    if (data.toString() === 'PING') {
      clients.get(id).lastHeartbeat = Date.now();
      socket.write('PONG');
    }
  });
});

// 每10秒檢查一次客戶端心跳
setInterval(() => {
  const now = Date.now();
  for (const [id, client] of clients.entries()) {
    // 如果客戶端30秒沒有心跳,斷開連接
    if (now - client.lastHeartbeat > 30000) {
      console.log(`客戶端 ${id} 心跳超時,斷開連接`);
      client.socket.destroy();
      clients.delete(id);
    }
  }
}, 10000);

// 客戶端心跳
const client = net.createConnection({ port: 3000 });
setInterval(() => {
  client.write('PING');
}, 10000);

Q: 如何處理大量數(shù)據(jù)傳輸?

A: 使用流控制和數(shù)據(jù)分塊:

const fs = require('fs');

// 發(fā)送大文件
function sendLargeFile(socket, filePath) {
  const fileStream = fs.createReadStream(filePath);
  
  fileStream.on('data', (chunk) => {
    // 檢查緩沖區(qū)是否已滿
    const canContinue = socket.write(chunk);
    
    if (!canContinue) {
      // 如果緩沖區(qū)已滿,暫停讀取
      fileStream.pause();
      
      // 當(dāng)緩沖區(qū)清空后,恢復(fù)讀取
      socket.once('drain', () => {
        fileStream.resume();
      });
    }
  });
  
  fileStream.on('end', () => {
    console.log('文件發(fā)送完成');
  });
}

到此這篇關(guān)于Node.js net模塊的使用示例的文章就介紹到這了,更多相關(guān)Node.js net模塊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • Node.js創(chuàng)建子進(jìn)程的幾種實(shí)現(xiàn)方式

    Node.js創(chuàng)建子進(jìn)程的幾種實(shí)現(xiàn)方式

    這篇文章主要介紹了Node.js創(chuàng)建子進(jìn)程的幾種實(shí)現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • nvm安裝方法以及安裝后node不能使用解決

    nvm安裝方法以及安裝后node不能使用解決

    在我們的日常開發(fā)中經(jīng)常會遇到這種情況,手上有好幾個項(xiàng)目,每個項(xiàng)目的需求不同,進(jìn)而不同項(xiàng)目必須依賴不同版的NodeJS運(yùn)行環(huán)境,nvm應(yīng)運(yùn)而生,這篇文章主要給大家介紹了關(guān)于nvm安裝方法以及安裝后node不能使用解決的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • 從零開始開發(fā)一個 MCP Server!

    從零開始開發(fā)一個 MCP Server!

    韓老師分享了如何使用Node.js開發(fā)一個MCP服務(wù)器的詳細(xì)過程,包括安裝Node.js、ScaffoldingTool、創(chuàng)建項(xiàng)目、實(shí)現(xiàn)代碼邏輯、調(diào)試和測試、發(fā)布等步驟
    2025-05-05
  • Node.js readline 逐行讀取、寫入文件內(nèi)容的示例

    Node.js readline 逐行讀取、寫入文件內(nèi)容的示例

    本篇文章主要介紹了Node.js readline逐行讀取、寫入文件內(nèi)容的示例,運(yùn)用readline逐行讀取的兩種實(shí)現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Node.js中require的工作原理淺析

    Node.js中require的工作原理淺析

    這篇文章主要介紹了Node.js中require的工作原理淺析,通過分析node.js的源碼得到本文,需要的朋友可以參考下
    2014-06-06
  • socket.io學(xué)習(xí)教程之基礎(chǔ)介紹(一)

    socket.io學(xué)習(xí)教程之基礎(chǔ)介紹(一)

    socket.io提供了基于事件的實(shí)時雙向通訊,所以下面這篇文章主要介紹了關(guān)于socket.io的相關(guān)資料,主要介紹了學(xué)習(xí)socket.io的基礎(chǔ)知識,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-04-04
  • node.js爬取中關(guān)村的在線電瓶車信息

    node.js爬取中關(guān)村的在線電瓶車信息

    這篇文章主要給大家介紹了關(guān)于利用node.js如何爬取中關(guān)村的在線電瓶車信息的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用node.js具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • 用純Node.JS彈出Windows系統(tǒng)消息提示框?qū)嵗?MessageBox)

    用純Node.JS彈出Windows系統(tǒng)消息提示框?qū)嵗?MessageBox)

    這篇文章主要介紹了用純Node.JS彈出Windows系統(tǒng)消息提示框?qū)嵗?MessageBox),非常具有實(shí)用價值,需要的朋友可以參考下
    2017-05-05
  • npm錯誤errno?-4048解決辦法

    npm錯誤errno?-4048解決辦法

    這篇文章主要給大家介紹了關(guān)于npm錯誤errno?-4048解決的相關(guān)資料,這個錯誤代碼通常表示文件系統(tǒng)錯誤或者硬件故障引起的問題,文中通過圖文將解決的辦法介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Windows下安裝 node 的版本控制工具 nvm

    Windows下安裝 node 的版本控制工具 nvm

    這篇文章主要介紹了Windows下安裝 node 的版本控制工具 nvm的相關(guān)資料,需要的朋友可以參考下
    2020-02-02

最新評論

始兴县| 彭阳县| 安溪县| 余江县| 花莲市| 龙门县| 米泉市| 石景山区| 股票| 黑水县| 上饶市| 嘉义市| 肥西县| 施甸县| 元谋县| 邻水| 宝鸡市| 秀山| 花垣县| 松江区| 疏勒县| 正安县| 无棣县| 锦州市| 波密县| 桦甸市| 巴楚县| 江津市| 余姚市| 盐池县| 石狮市| 吉安县| 吐鲁番市| 永顺县| 宜川县| 阿瓦提县| 洛扎县| 林西县| 峡江县| 睢宁县| 牟定县|