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

華為雲開發者社區 2021-09-18 11:57:09 阅读数:75

一文 搞懂 使用 node.js node

​​​​​​摘要: 網絡是通信互聯的基礎,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.
  • 3.

1.2、監聽客戶端的連接

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

server.listen(port[, host][, backlog][, callback]);
port:為需要監聽的端口號,參數值為0的時候將隨機分配一個端口號;
host:服務器地址;
backlog:連接等待隊列的最大長度;
callback:回調函數。
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

以下代碼可以創建一個TCP服務器並監聽8001端口:

//引入net模塊
const net = require('net');
//創建TCP服務器
const server = net.createServer(function (socket) {
console.log('有新的客戶端接入');
});
//設置監聽端口
server.listen(8001, function () {
console.log('服務正在監聽中。。。')
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

運行這段代碼,可以在控制臺看到執行了listen方法的回調函數,如圖所示:

可以使用相應的TCP客戶端或者調試工具來連接這個已經創建好的TCP服務器。例如,要使用Windows的Telnet就可以用以下命令來連接:

telnet localhost 8001
  • 1.

連接成功後可以看到控制臺打印了“有新的客戶端接入”字樣,錶明createServer方法的回調函數已經執行,說明已經成功連接到這個創建好的TCP服務器。

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

//設置監聽端口
server.listen(8001);
//設置監聽時的回調函數
server.on('listening', function () {
console.log("服務正在監聽中。。。")
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

除了listening事件外,TCP服務器還支持以下事件:

connection:當有新的鏈接創建時觸發,回調函數的參數為socket連接對象。
close:TCP服務器關閉的時候觸發,回調函數沒有參數。
error:TCP服務器發生錯誤的時候觸發,回調函數的參數為error對象。
  • 1.
  • 2.
  • 3.

下列代碼通過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.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

1.3、查看服務器監聽的地址

當創建了一個TCP服務器後,可以通過server.address()方法來查看這個TCP服務器監聽的地址,並返回一個JSON對象,因為這個方法返回的是TCP服務器監聽的地址信息,所以應該在調用了server.listen()方法或者綁定了事件listening中的回調函數中調用該方法。這個對象的屬性有:

port:TCP服務器監聽的端口號;
family:說明TCP服務器監聽的地址是IPv6還是IPv4;
address:TCP服務器監聽的地址。
  • 1.
  • 2.
  • 3.

代碼如下:

//引入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);
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

運行結果如圖:

1.4、連接服務器的客戶端數量

創建一個TCP服務器後,可以通過server.getConnections()方法獲取連接這個TCP服務器的客戶端數量。這個方法是一個异步的方法,回調函數有兩個參數:

第一個參數為error對象。
第二個參數為連接TCP服務器的客戶端數量。
  • 1.
  • 2.

除了獲取連接數外,也可以通過設置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("服務正在監聽中。。。")
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

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

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("服務正在監聽中。。。")
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

測試結果如下:

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("服務正在監聽中。。。")
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

測試結果如下:

在上面這段代碼中還用到了socket對象的bytesWritten和bytesRead屬性,這兩個屬性分別代錶著發送數據的字節數和接收數據的字節數。除了上面這兩個屬性外,socket對象還有以下屬性:

socket.localPort:本地端口的地址;
socket.localAddress:本地IP地址;
socket.remotePort:進程端口地址;
socket.remoteFamily:進程IP協議族;
socket.remoteAddress:進程IP地址。
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

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();
  • 1.
  • 2.
  • 3.
  • 4.

創建一個socket對象的時候可以傳入一個json對象。這個對象有以下屬性:

fd:指定一個存在的文件描述符,默認值為null;
readable:是否允許在這個socket上讀,默認值為false;
writeable:是否允許在這個socket上寫,默認值為false;
allowHalfOpen:該屬性為false時,TCP服務器接收到客戶端發送的一個FIN包後,將會回發一個FIN包;該屬性為true時,TCP服務器接收到客戶端發送的一個FIN包後不會回發FIN包。
  • 1.
  • 2.
  • 3.
  • 4.

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("連接服務器成功");
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

連接成功如下圖所示:

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());
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

先啟動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("客戶端發送數據結束")
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

客戶端控制臺輸出:

服務端控制臺輸出:

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


 ​點擊關注,第一時間了解華為雲新鮮技術~​

版权声明:本文为[華為雲開發者社區]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/09/20210918115708877T.html