溫馨提示×

溫馨提示×

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

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

Nodejs中的net模塊怎么用

發(fā)布時間:2022-04-12 10:12:14 來源:億速云 閱讀:162 作者:iii 欄目:web開發(fā)

這篇文章主要介紹了Nodejs中的net模塊怎么用的相關(guān)知識,內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Nodejs中的net模塊怎么用文章都會有所收獲,下面我們一起來看看吧。

Nodejs中的net模塊怎么用

1. OSI 七層協(xié)議模型

想要學(xué)明白通信模塊,就不得不了解網(wǎng)絡(luò)通信模型,想要記住網(wǎng)絡(luò)通信模型,就不得不實際操作來輔助記憶. 這個是面試的重點. 這一塊內(nèi)容很多,想要跟深入的了解,還說需要體系的學(xué)習(xí)的. 這里只是簡單提提.

寄出這張老圖:

Nodejs中的net模塊怎么用

對于我們前端而言, 需要記住 TCP/IP 協(xié)議簇的體系結(jié)果既可.

  • 應(yīng)用層: http(80 端口)、FTP(21)、SMTP(發(fā)送郵件)、POP(接收郵件)、DNS

  • 傳輸層: TCP/ UDP

  • 網(wǎng)際層: IP,ICMP(是 IP 層的附屬協(xié)議)

  • 數(shù)據(jù)鏈路層: PPP, SLIP

  • 物理層: 網(wǎng)有雙絞線、同軸電纜、光纖等傳輸方式, 遵循 ISO2110 規(guī)范

ICMP這種依附于 IP 協(xié)議的協(xié)議可以知道,對于網(wǎng)絡(luò)協(xié)議的分層不用過于較勁. ICMP明明需要 IP 協(xié)議為基礎(chǔ),但是它也被規(guī)劃為網(wǎng)絡(luò)層. 我們對于 OSI 模型的正確的認(rèn)識,我認(rèn)為應(yīng)該是用 OSI 模型來進(jìn)行問題的分析比用來對于協(xié)議進(jìn)行所謂的分層更加來得有意義.

TCP/IP 協(xié)議簇 并不是只是指 TCP 和 IP 協(xié)議,只是因為這兩個協(xié)議過于出圈,所以就用 TCP/IP 來統(tǒng)稱互聯(lián)網(wǎng)相關(guān)聯(lián)的協(xié)議集合起來. 還有另外一種說法是,在使用 TCP/IP 協(xié)議過程中使用到的協(xié)議族的統(tǒng)稱.

而客戶端和服務(wù)端的傳輸流如下

Nodejs中的net模塊怎么用

如果角色變成發(fā)送者接受者的時候,傳輸流如下圖:

Nodejs中的net模塊怎么用

可以看出來傳輸?shù)倪^程中,從發(fā)送端開始,沒經(jīng)過一層協(xié)議都會加上所需要的首部信息.層層把關(guān),層層加碼. 然后到了接收端的時候, 就反而行之, 每經(jīng)過一層都剝?nèi)?yīng)的首部. 只等到最后拿到的 HTTP 數(shù)據(jù).

上面圖片出自《圖解 HTTP》

上面就是大體的網(wǎng)絡(luò)協(xié)議模型.

疑惑: 為什么書上和很多地方在把 OSI 體系結(jié)果中合并成 TCP/IP 五層協(xié)議之后,網(wǎng)絡(luò)層的名稱會變成網(wǎng)際層呢?

2. TCP 連接

Nodejs中的net模塊怎么用

第一次握手: 客戶端向服務(wù)端發(fā)送 SYN 標(biāo)志位(序號是 J), 并進(jìn)入 SYN_SENT 狀態(tài)(等待服務(wù)端確認(rèn)狀態(tài))

第二次握手: 服務(wù)端收到來自客戶端的 SYN J, 服務(wù)端會確認(rèn)該數(shù)據(jù)包已收到并發(fā)送 ACK 標(biāo)志位(序號是 J + 1)和 SYN 標(biāo)志位(序號是 K), 隨后進(jìn)入 SYN_REVD 狀態(tài)(請求接受并等待客戶端確認(rèn)狀態(tài))

第三次握手: 客戶端進(jìn)入連接建立狀態(tài)后,向服務(wù)端發(fā)送 ACK 標(biāo)志位(K+ 1) , 確認(rèn)客戶端已收到建立連接,服務(wù)器收到 ACK 標(biāo)志后,服務(wù)端進(jìn)入連接已建立狀態(tài).

J 和 K 都是為了確立是誰在請求. SYN 和 ACK 的結(jié)構(gòu)沒有什么不同,只是發(fā)送的對象不一樣.

3. net 模塊

net模塊就是對于上面 TCP 連接的具體實現(xiàn).

首先, 學(xué)習(xí) API 依舊推薦直接進(jìn)入官方文檔. 其中中文文檔內(nèi)容不會是最新版本的

在學(xué)習(xí)的時候,能夠有時間看英文文檔就盡量看英文文檔. 對于這一點我堅持了半年. 從一開始看不下去,直到現(xiàn)在能夠可以忍住不舒適感看下去. 半年時間進(jìn)步就很明顯了. 而且這種不舒適感是一件好事,說明這個不是你的舒適區(qū),畢竟勇于跨過自己的舒適區(qū)才是進(jìn)步的源泉

接下來,進(jìn)行正題.既然要學(xué)習(xí)通信,那么我們就需要兩個對象來模擬客戶端和服務(wù)端.分別建立client.jsservice.js兩個文件. 通過命令行創(chuàng)建:

touch client.js && touch service.js

3.1 service.js 部分

引入net模塊,并讓服務(wù)器進(jìn)入LISTENT狀態(tài), 以及配置端口號和 HOST 地址(手動略過 DNS 解析過程), 等待客戶端的召喚

const net = require("net");
const post = 3306;
const host = "127.0.0.1";

const server = net.createServer();
server.listen(post, host);

此時服務(wù)器對應(yīng)了 TCP 連接中服務(wù)器LISTEN狀態(tài).

隨后監(jiān)聽一些必要的事件,也就是 server 提供的鉤子. (屬于 event 相關(guān)知識)

server.on("listening", () => {
  console.log("服務(wù)器已經(jīng)可以連接啦");
});

server.on("connection", (socket) => {
  console.log("有客戶端來訪咯");
});

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

server.on("error", (error) => {
  console.log("服務(wù)器出錯啦: ", error); // error 有錯誤的信息
});

上面這一串代碼涉及到了,

  • listening: 監(jiān)聽端口后出發(fā)的事件

  • connection: 有客戶端來訪的時候觸發(fā)事件

  • close: 服務(wù)器關(guān)閉觸發(fā)

  • error: 服務(wù)器出錯觸發(fā)

對于close我們需要注意的是,后臺大哥一般是直接

ps
kill -9 pid

通過殺死線程的方式來進(jìn)行的

connection狗子中, 形參是 socket 命名. 它的中文翻譯為嵌套字, 被 node 封裝成了 stream(流).在可以粗淺的理解為就是客戶端發(fā)送過來的數(shù)據(jù). 這是這個數(shù)據(jù)自身是有方法的. 我在connection中對socket來進(jìn)行處理

server.on("connection", (socket) => {
  console.log("有客戶端來訪咯");

  socket.on("data", (data) => {
    console.log(data); // 客戶端發(fā)送過來的數(shù)據(jù)
  });
});

stream 以后的文章會進(jìn)行介紹.

服務(wù)端既然能夠接受客戶端發(fā)過來的數(shù)據(jù),自然也能夠給客戶端回復(fù). 在socket.on中寫入(當(dāng)然也可以寫在外面):

socket.write("我已經(jīng)收到你的服務(wù)器了哦,客戶端");

此時如果客戶端已經(jīng)完成了數(shù)據(jù)的接受,然后關(guān)閉了連接.我們可以也可以通過socket.on('close‘)鉤子監(jiān)聽到:

socket.on("close", () => {
  console.log("客戶端把另外一頭的流給關(guān)了");
});

對于socket事件的總結(jié)放入client.js中. 此時service.js的所有內(nèi)容如下:

const net = require("net");
const post = 3306;
const host = "127.0.0.1";

const server = net.createServer();
server.listen(post, host);

server.on("listening", () => {
  console.log("服務(wù)器已經(jīng)可以連接啦");
});

server.on("connection", (socket) => {
  console.log("有客戶端來訪咯");

  socket.on("data", (data) => {
    console.log(data); // 客戶端發(fā)送過來的數(shù)據(jù)

    socket.write("我已經(jīng)收到你的服務(wù)器了哦,客戶端");
  });

  socket.on("close", () => {
    console.log("客戶端把另外一頭的流給關(guān)了");
    server.close(); // 客戶端已經(jīng)不要數(shù)據(jù)了,那么我們就把服務(wù)器給關(guān)閉了吧
  });
});

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

server.on("error", (error) => {
  console.log("服務(wù)器出錯啦: ", error); // error 有錯誤的信息
});

3.2 client.js 部分

客戶端的就簡單很多.

const net = require("net");
const post = 3306;
const host = "127.0.0.1";

const socket = net.connect(post, host);

socket.on("connect", () => {
  console.log("已經(jīng)連接到服務(wù)器了哦");
});

socket.write("服務(wù)器, 我來了");
socket.on("data", (data) => {
  console.log(data.toString());
  socket.end();
});

socket.on("close", () => {
  console.log("連接已關(guān)閉了");
});

對于socket的事件的總結(jié)

  • connect: 成功和服務(wù)器連接觸發(fā)

  • data: 接受到服務(wù)器發(fā)過來的參數(shù)

  • end: 數(shù)據(jù)接收完畢之后可以觸發(fā)

  • close: socket 關(guān)閉觸發(fā)

service.jsclient.js框架已經(jīng)寫完, 那些先后在打開兩個終端運行他們:

node service.js
node client.js

自行查看打印的結(jié)果.

整個 TCP 連接的框架大體就已經(jīng)完成了. 當(dāng)然實際的生產(chǎn)遠(yuǎn)遠(yuǎn)不止這些. 還要處理粘包、拆包/封包, 心跳包等等.


關(guān)于“Nodejs中的net模塊怎么用”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“Nodejs中的net模塊怎么用”知識都有一定的了解,大家如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI