一文搞懂如何使用Node.js進行TCP網路通訊

華為雲開發者社群發表於2021-09-18
摘要: 網路是通訊互聯的基礎,Node.js提供了net、http、dgram等模組,分別用來實現TCP、HTTP、UDP的通訊,本文主要對使用Node.js的TCP通訊部份進行實踐記錄。

本文分享自華為雲社群《一文搞懂如何使用Node.js進行TCP網路通訊》,作者:lwq1228 。

1、構建TCP伺服器

1.1、使用Node.js建立TCP伺服器

為了使用Node.js建立TCP伺服器,首先要呼叫require(‘net’)來載入net模組,然後呼叫net模組的createServer方法就可以輕鬆地建立一個TCP伺服器,語法格式如下:

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

options是一個物件引數值,有兩個布林型別的屬性allowHalfOpen和pauseOnConnect。這兩個屬性預設都是false;
connectionListener是一個當客戶端與服務端建立連線時的回撥函式,這個回撥函式以socket埠物件作為引數。

1.2、監聽客戶端的連線

使用TCP伺服器的listen方法就可以開始監聽客戶端的連線,語法格式如下:

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

port:為需要監聽的埠號,引數值為0的時候將隨機分配一個埠號;
host:伺服器地址;
backlog:連線等待佇列的最大長度;
callback:回撥函式。

以下程式碼可以建立一個TCP伺服器並監聽8001埠:

//引入net模組
const net = require('net');
//建立TCP伺服器
const server = net.createServer(function (socket) {
    console.log('有新的客戶端接入');
});
//設定監聽埠
server.listen(8001, function () {
    console.log('服務正在監聽中。。。')
});

執行這段程式碼,可以在控制檯看到執行了listen方法的回撥函式,如圖所示:

一文搞懂如何使用Node.js進行TCP網路通訊

可以使用相應的TCP客戶端或者除錯工具來連線這個已經建立好的TCP伺服器。例如,要使用Windows的Telnet就可以用以下命令來連線:

telnet localhost 8001

連線成功後可以看到控制檯列印了“有新的客戶端接入”字樣,表明createServer方法的回撥函式已經執行,說明已經成功連線到這個建立好的TCP伺服器。

一文搞懂如何使用Node.js進行TCP網路通訊

server.listen()方法其實觸發的是server下的listening事件,所以也可以手動監聽listening事件,程式碼如下:

//設定監聽埠
server.listen(8001);
//設定監聽時的回撥函式
server.on('listening', function () {
    console.log("服務正在監聽中。。。")
});

除了listening事件外,TCP伺服器還支援以下事件:

connection:當有新的連結建立時觸發,回撥函式的引數為socket連線物件。
close:TCP伺服器關閉的時候觸發,回撥函式沒有引數。
error:TCP伺服器發生錯誤的時候觸發,回撥函式的引數為error物件。

下列程式碼通過net.Server類來建立一個TCP伺服器,新增以上事件:

//引入net模組
const net = require('net');
//例項化一個伺服器物件
const server = new net.Server();
//監聽connection事件
server.on('connection', function (socket) {
    console.log('有新的客戶端接入');
});
//設定監聽埠
server.listen(8001);
//設定監聽時的回撥函式
server.on('listening', function () {
    console.log('服務正在監聽中。。。');
});
//設定關閉時的回撥函式
server.on('close', function () {
    console.log('服務已關閉');
});
//設定出錯時的回撥函式
server.on('error', function (err) {
    console.log('服務執行異常', err);
});

1.3、檢視伺服器監聽的地址

當建立了一個TCP伺服器後,可以通過server.address()方法來檢視這個TCP伺服器監聽的地址,並返回一個JSON物件,因為這個方法返回的是TCP伺服器監聽的地址資訊,所以應該在呼叫了server.listen()方法或者繫結了事件listening中的回撥函式中呼叫該方法。這個物件的屬性有:

port:TCP伺服器監聽的埠號;
family:說明TCP伺服器監聽的地址是IPv6還是IPv4;
address:TCP伺服器監聽的地址。

程式碼如下:

//引入net模組
const net = require('net');
//建立TCP伺服器
const server = net.createServer(function (socket) {
    console.log('有新的客戶端接入');
});
//設定監聽埠
server.listen(8001);
//設定監聽時的回撥函式
server.on('listening', function () {
    //獲取地址資訊
    let address = server.address();
    //獲取地址詳細資訊
    console.log("伺服器監聽的埠是:" + address.port);
    console.log("伺服器監聽的地址是:" + address.address);
    console.log("伺服器監聽的地址型別是:" + address.family);
});

執行結果如圖:

一文搞懂如何使用Node.js進行TCP網路通訊

1.4、連線伺服器的客戶端數量

建立一個TCP伺服器後,可以通過server.getConnections()方法獲取連線這個TCP伺服器的客戶端數量。這個方法是一個非同步的方法,回撥函式有兩個引數:

第一個引數為error物件。
第二個引數為連線TCP伺服器的客戶端數量。

除了獲取連線數外,也可以通過設定TCP伺服器的maxConnections屬性來設定這個TCP伺服器的最大連線數。當連線數超過最大連線數的時候,伺服器將拒絕新的連線。如下程式碼設定這個TCP伺服器的最大連線數為3。

//引入net模組
const net = require('net');
//建立TCP伺服器
const server = net.createServer(function (socket) {
    console.log('有新的客戶端接入');
    //設定最大連線數量
    server.maxConnections = 3;
    server.getConnections(function (err, count) {
        console.log("當前連線的客戶端個數為:" + count);
    });
});
//設定監聽埠
server.listen(8001, function () {
    console.log("服務正在監聽中。。。")
});

執行這段程式碼,並嘗試用多個客戶端連線。可以發現當客戶端連線數超過3的時候,新的客戶端就無法連線這個伺服器了,如圖所示:

一文搞懂如何使用Node.js進行TCP網路通訊

1.5、獲取客戶端傳送的資料

createServer方法的回撥函式引數是一個net.Socket物件(伺服器所監聽的埠物件),這個物件同樣也有一個address()方法,用來獲取TCP伺服器繫結的地址,同樣也是返回一個含有port、family、address屬性的物件。通過socket物件可以獲取客戶端傳送的流資料,每次接收到資料的時候觸發data事件,通過監聽這個事件就可以在回撥函式中獲取客戶端傳送的資料,程式碼如下:

//引入net模組
const net = require('net');
//建立TCP伺服器
const server = net.createServer(function (socket) {
    //監聽data事件
    socket.on("data", function (data) {
        //列印資料
        console.log("接收到資料:" + data.toString());
    });
});
//設定監聽埠
server.listen(8001, function () {
    console.log("服務正在監聽中。。。")
});

測試結果如下:

一文搞懂如何使用Node.js進行TCP網路通訊

socket物件除了有data事件外,還有connect、end、error、timeout等事件。

1.6、傳送資料給客戶端

呼叫socket.write()可以使TCP伺服器傳送資料,這個方法只有一個必需引數,就是需要傳送的資料;第二個引數為編碼格式,可選。同時,可以為這個方法設定一個回撥函式。當有使用者連線TCP伺服器的時候,將傳送資料給客戶端,程式碼如下:

//引入net模組
const net = require('net');
//建立TCP伺服器
const server = net.createServer(function (socket) {
    //設定訊息內容
    const message = "Hello Client......";
    //傳送資料
    socket.write(message, function () {
        const writeSize = socket.bytesWritten;
        console.log("資料傳送成功,資料長度為:" + writeSize);
    });

    //監聽data事件
    socket.on("data", function (data) {
        const readSize = socket.bytesRead;
        //列印資料
        console.log("接收到資料為:" + data.toString(), ";接收的資料長度為:" + readSize);
    });
});
//設定監聽埠
server.listen(8001, function () {
    console.log("服務正在監聽中。。。")
});

測試結果如下:

一文搞懂如何使用Node.js進行TCP網路通訊

在上面這段程式碼中還用到了socket物件的bytesWritten和bytesRead屬性,這兩個屬性分別代表著傳送資料的位元組數和接收資料的位元組數。除了上面這兩個屬性外,socket物件還有以下屬性:

socket.localPort:本地埠的地址;
socket.localAddress:本地IP地址;
socket.remotePort:程式埠地址;
socket.remoteFamily:程式IP協議族;
socket.remoteAddress:程式IP地址。

2、構建TCP客戶端

Node.js在建立一個TCP客戶端的時候同樣使用的是net(網路)模組。

2.1、使用Node.js建立TCP客戶端

為了使用Node.js建立TCP客戶端,首先要呼叫require(‘net’)來載入net模組。建立一個TCP客戶端只需要建立一個連線TCP客戶端的socket物件即可:

//引入net模組
const net = require('net');
//建立TCP客戶端
const client = new net.Socket();

建立一個socket物件的時候可以傳入一個json物件。這個物件有以下屬性:

fd:指定一個存在的檔案描述符,預設值為null;
readable:是否允許在這個socket上讀,預設值為false;
writeable:是否允許在這個socket上寫,預設值為false;
allowHalfOpen:該屬性為false時,TCP伺服器接收到客戶端傳送的一個FIN包後,將會回發一個FIN包;該屬性為true時,TCP伺服器接收到客戶端傳送的一個FIN包後不會回發FIN包。

2.2、連線TCP伺服器

建立了一個socket物件後,呼叫socket物件的connect()方法就可以連線一個TCP伺服器,程式碼如下:

//引入net模組
const net = require('net');
//建立TCP客戶端
const client = new net.Socket();
//設定連線的伺服器
client.connect(8001, '127.0.0.1', function () {
    console.log("連線伺服器成功");
});

連線成功如下圖所示:

一文搞懂如何使用Node.js進行TCP網路通訊

2.3、獲取從TCP伺服器傳送的資料

socket物件有data、error、close、end等事件,因可以通過監聽data事件來獲取從TCP伺服器傳送的資料,程式碼如下:

//引入net模組
const net = require('net');
//建立TCP客戶端
const client = new net.Socket();
//設定連線的伺服器
client.connect(8001, '127.0.0.1', function () {
    console.log("連線伺服器成功");
});
//監聽data事件
client.on("data", function (data) {
    //列印資料
    console.log("接收到資料為:" + data.toString());
});

先啟動TCP服務端,再執行上面客戶端,可以發現命令列中已經輸出了來自服務端的資料,說明此時已經實現了服務端和客戶端之間的通訊:

一文搞懂如何使用Node.js進行TCP網路通訊

2.4、向TCP伺服器傳送資料

因為TCP客戶端是一個socket物件,所以可以使用以下程式碼來向TCP伺服器傳送資料:

//引入net模組
const net = require('net');
//建立TCP客戶端
const client = new net.Socket();
//設定連線的伺服器
client.connect(8001, '127.0.0.1', function () {
    console.log("連線伺服器成功");
    //給服務端傳送資料
    client.write("Hello Server......");
});
//監聽data事件
client.on("data", function (data) {
    //列印資料
    console.log("接收到資料為:" + data.toString());
});
//監聽end事件
client.on("end", function () {
    console.log("客戶端傳送資料結束")
});

客戶端控制檯輸出:

一文搞懂如何使用Node.js進行TCP網路通訊

服務端控制檯輸出:

一文搞懂如何使用Node.js進行TCP網路通訊

至此使用Node.js進行TCP網路通訊完成,如有不對的地方歡迎指正

 

點選關注,第一時間瞭解華為雲新鮮技術~

相關文章