Linux——匿名管道

Linux——匿名管道

  • 什么是管道
  • 匿名管道的底層原理
  • 觀察匿名管道現象
    • 讀寫端的幾種情況
    • 寫端慢,讀端快
    • 寫端快,讀端慢
  • 管道的大小
    • 寫端關閉,讀端一直讀
    • 寫端一直寫,讀端關閉

我們之前一直用的是vim來編寫代碼,現在有了vscode這樣強大的編輯器,我們可以把我們的vim放一邊了,如果還有小伙伴還沒有配置好vscode的遠端,可以點擊這里:

https://blog.csdn.net/qq_67693066/article/details/136368891

我們今天進入管道的學習:

什么是管道

在計算機領域,管道(Pipeline)是一種將多個命令連接在一起以形成數據流的機制。它允許一個命令的輸出成為另一個命令的輸入,從而實現命令之間的數據傳遞和處理。

在 Unix/Linux 系統中,管道通常用豎線符號 | 表示。通過管道,可以將一個命令的輸出傳遞給另一個命令進行處理,從而構建復雜的數據處理流程。

例如,假設我們有兩個命令 command1 和 command2,我們可以使用管道將它們連接起來:

command1 | command2

這將會把 command1 的輸出作為 command2 的輸入,command2 將處理 command1 的輸出并生成最終的結果。

管道的優勢包括:

簡化復雜任務: 管道可以將多個簡單的命令組合成一個復雜的任務,使得任務的實現更加簡單和高效。
模塊化和可重用性: 通過將命令連接在一起,可以更好地組織代碼并提高代碼的可重用性。每個命令都可以專注于完成一個特定的任務。
減少臨時文件: 管道可以避免將數據存儲到臨時文件中,從而減少了文件 I/O 的開銷和磁盤空間的占用。
實時處理: 管道允許命令之間的實時數據傳遞,這對于需要連續處理數據的任務非常有用,比如日志處理、數據流分析等。

簡單來說,管道就是連接多個指令。我們之前也在頻繁使用管道:比如我們想統計當前登錄到系統的用戶數量。
在這里插入圖片描述
who指令的結果作為wc -l的輸入。

匿名管道的底層原理

我們這里講的簡單一點,現在我們有一個進程,它自身會被以讀和寫的方式分別打開一次:
在這里插入圖片描述
然后這個讀和寫都會往一個緩沖區輸入輸出數據:

這個時候父進程創建子進程,子進程發生淺拷貝,指向沒有發生變化:
在這里插入圖片描述
這里注意一下,管道一般是單向的,所以我們現在想讓父進程讀,讓子進程寫
在這里插入圖片描述
這樣形成了一個單向通道,這個就是一個基本的匿名管道

匿名管道(Anonymous Pipe)是一種用于進程間通信的機制,特別是在 Unix 和類 Unix 系統中。它允許一個進程將輸出發送到另一個進程的輸入,從而實現進程間的數據傳輸。
以下是匿名管道的一些關鍵特點:
單向通信:匿名管道是單向的,只能支持單向數據流。它只能用于單一方向的通信,通常是父進程到子進程或者相反。
創建:匿名管道通過調用系統調用 pipe() 來創建。這個系統調用創建了一個管道,返回兩個文件描述符,其中一個用于讀取管道,另一個用于寫入管道。
父子進程通信:通常,匿名管道用于父子進程之間的通信。在創建子進程后,父進程可以將數據寫入管道,而子進程則可以從管道中讀取這些數據。
半雙工:匿名管道是半雙工的,意味著數據只能在一個方向上流動。如果需要雙向通信,則需要創建兩個管道,或者使用其他的進程間通信機制,比如命名管道或套接字。
進程同步:匿名管道通常用于進程間的同步和協作。一個進程可能會阻塞在讀取管道上,直到另一個進程寫入數據到管道中為止。
匿名管道在 Unix 系統中被廣泛應用,特別是在 shell 編程和進程間通信方面。它提供了一種簡單而有效的方式,允許不同進程之間進行數據交換和協作

我也有專門創建管道的函數pipe
在這里插入圖片描述
我們可以來試一下:

#include<iostream>
#include<unistd.h>
#include<cassert>
using namespace std;int main()
{int pipefd[2] = {0};int n = pipe(pipefd);assert(n == 0);cout<<"pipefd[0]"<<"--->"<<pipefd[0]<<"pipefd[1]"<<"--->"<<pipefd[1]<<endl;return 0;
}

運行:
在這里插入圖片描述
這里我們發現pipefd[0]指代的是3,而我們的pipefd[1]指代的是4。其實也很好理解,因為0,1,2被標準輸入,標準輸出,標準錯誤占了。所以從3開始。

同時,如果我么查手冊會看到這樣一段話:
在這里插入圖片描述
這段話的主要意思是pipefd[0]是讀端,而pipefd[1]是寫端。這為我們以后哪個開哪個關提供了依據。

觀察匿名管道現象

我們先搭建架子來觀察我們匿名管道的現象:

#include<iostream>
#include<unistd.h>
#include<cassert>
#include<sys/types.h>
#include<sys/wait.h>
using namespace std;int main()
{//建立管道int pipefd[2] = {0};int n = pipe(pipefd);assert(n == 0);//創建子進程pid_t id = fork();//子進程if(id < 0){perror("fork fail");}if(id ==0){//子進程要做的事exit(0);}//父進程要做的事//回收子進程pid_t rid = waitpid(id,nullptr,0);if(rid == id){cout<<"wait success"<<endl;}return 0;
}

現在我們想讓子進程寫,父進程讀,我們把相應用不到的管道關閉:

#include<iostream>
#include<unistd.h>
#include<cassert>
#include<sys/types.h>
#include<sys/wait.h>
using namespace std;int main()
{//建立管道int pipefd[2] = {0};int n = pipe(pipefd);assert(n == 0);//創建子進程pid_t id = fork();//子進程if(id < 0){perror("fork fail");return 1;}if(id ==0){//子進程要做的事close(pipefd[0]); //關閉讀的通道exit(0);}//父進程要做的事close(pipefd[1]); //關閉寫的通道//回收子進程pid_t rid = waitpid(id,nullptr,0);if(rid == id){cout<<"wait success"<<endl;}return 0;
}

我們讓子進程寫入一些東西,然后讓父進程來讀,看看行不行:

#include<iostream>
#include<unistd.h>
#include<cassert>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<string.h>
using namespace std;
#define MAX 1024int main()
{//建立管道int pipefd[2] = {0};int n = pipe(pipefd);assert(n == 0);//創建子進程pid_t id = fork();//子進程if(id < 0){perror("fork fail");return 1;}if(id ==0){//子進程要做的事close(pipefd[0]); //關閉讀的通道//向管道寫入int cnt = 10;while(cnt){//緩沖區char message[MAX];//向緩沖區里寫snprintf(message,sizeof(message),"hello father I am child my pid:%d cnt:%d ", getpid(),cnt);cnt--;//向管道寫write(pipefd[1],message,strlen(message));sleep(1);}exit(0);}//父進程要做的事close(pipefd[1]); //關閉寫的通道//從管道中讀取數據char buffer[MAX];while(true){ssize_t n = read(pipefd[0],buffer,sizeof(buffer));if(n > 0){cout << getpid() << "," << "chid say :" << buffer << "to me" << endl;}}//回收子進程pid_t rid = waitpid(id,nullptr,0);if(rid == id){cout<<"wait success"<<endl;}return 0;
}

在這里插入圖片描述
我們看到父進程真的拿到了子進程寫的東西,這就是一個最基本的管道的應用。

讀寫端的幾種情況

寫端慢,讀端快

我們模擬一下,寫端慢,讀端快的情況

#include<iostream>
#include<unistd.h>
#include<cassert>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<string.h>
using namespace std;
#define MAX 1024int main()
{//建立管道int pipefd[2] = {0};int n = pipe(pipefd);assert(n == 0);//創建子進程pid_t id = fork();//子進程if(id < 0){perror("fork fail");return 1;}if(id ==0){//子進程要做的事close(pipefd[0]); //關閉讀的通道//向管道寫入int cnt = 10;while(cnt){//緩沖區char message[MAX];//向緩沖區里寫snprintf(message,sizeof(message),"hello father I am child my pid:%d cnt:%d ", getpid(),cnt);cnt--;//向管道寫write(pipefd[1],message,strlen(message));sleep(100); //模擬寫端慢}exit(0);}//父進程要做的事close(pipefd[1]); //關閉寫的通道//從管道中讀取數據char buffer[MAX];while(true){ssize_t n = read(pipefd[0],buffer,sizeof(buffer));if(n > 0){cout << getpid() << "," << "chid say :" << buffer << "to me" << endl;}}//回收子進程pid_t rid = waitpid(id,nullptr,0);if(rid == id){cout<<"wait success"<<endl;}return 0;
}

在這里插入圖片描述
我們發現父進程處于一個休眠的狀態,很明顯,它是在等待我們的子進程進行寫入。

這里我們可以得出匿名管道具有同步機制,讀端和寫端是協同工作的。

寫端快,讀端慢

我們調換一下,讓寫端快,讀端快:

#include<iostream>
#include<unistd.h>
#include<cassert>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<string.h>
using namespace std;
#define MAX 1024int main()
{//建立管道int pipefd[2] = {0};int n = pipe(pipefd);assert(n == 0);//創建子進程pid_t id = fork();//子進程if(id < 0){perror("fork fail");return 1;}if(id ==0){//子進程要做的事close(pipefd[0]); //關閉讀的通道//向管道寫入int cnt = 10000;while(cnt){//緩沖區char message[MAX];//向緩沖區里寫snprintf(message,sizeof(message),"hello father I am child my pid:%d cnt:%d ", getpid(),cnt);cnt--;//向管道寫write(pipefd[1],message,strlen(message));cout<<"writing......"<<endl;}exit(0);}//父進程要做的事close(pipefd[1]); //關閉寫的通道//從管道中讀取數據char buffer[MAX];while(true){sleep(2); //睡眠2秒ssize_t n = read(pipefd[0],buffer,sizeof(buffer));if(n > 0){cout << getpid() << "," << "chid say :" << buffer << "to me" << endl;}}//回收子進程pid_t rid = waitpid(id,nullptr,0);if(rid == id){cout<<"wait success"<<endl;}return 0;
}

執行:
在這里插入圖片描述
過了2秒之后:
在這里插入圖片描述
數據一瞬間出來了。

這里我們可以得出匿名管道是面向字節流的,它沒有硬性規定我寫一條你必須馬上讀一條,而是以字節流的形式讀或寫。

管道的大小

我們可以寫一段代碼來測試我們管道的大小:

#include<iostream>
#include<unistd.h>
#include<cassert>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<string.h>
using namespace std;
#define MAX 1024int main()
{//建立管道int pipefd[2] = {0};int n = pipe(pipefd);assert(n == 0);//創建子進程pid_t id = fork();//子進程if(id < 0){perror("fork fail");return 1;}if(id ==0){//子進程要做的事close(pipefd[0]); //關閉讀的通道//向管道寫入int cnt = 0;while(1){//   //緩沖區//   char message[MAX];//   //向緩沖區里寫//   snprintf(message,sizeof(message),"hello father I am child my pid:%d cnt:%d ", getpid(),cnt);//   cnt--;//   //向管道寫//   write(pipefd[1],message,strlen(message));//   cout<<"writing......"<<endl;char c = 'a';write(pipefd[1], &c, 1);cnt++;cout << "write ....: " << cnt << endl;}exit(0);}//父進程要做的事close(pipefd[1]); //關閉寫的通道//從管道中讀取數據char buffer[MAX];while(true){// sleep(2); //睡眠2秒// ssize_t n = read(pipefd[0],buffer,sizeof(buffer));// if(n > 0)// {//    cout << getpid() << "," << "chid say :" << buffer << "to me" << endl;// }}//回收子進程pid_t rid = waitpid(id,nullptr,0);if(rid == id){cout<<"wait success"<<endl;}return 0;
}

在這里插入圖片描述
我們發現最后結果是65536,折合下來也就是64kb左右的大小。

我們也可以用指令來查看管道大小:ulimit -a
在這里插入圖片描述

我們查看的管道大小為512 * 8 = 4kb,好像比我們看到的小。這個其實不是真正的大小。

寫端關閉,讀端一直讀

我們現在讓寫段寫一段時間后直接關閉,但是讀端沒有關閉:

#include<iostream>
#include<unistd.h>
#include<cassert>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<string.h>
using namespace std;
#define MAX 1024int main()
{//建立管道int pipefd[2] = {0};int n = pipe(pipefd);assert(n == 0);//創建子進程pid_t id = fork();//子進程if(id < 0){perror("fork fail");return 1;}if(id ==0){//子進程要做的事close(pipefd[0]); //關閉讀的通道//向管道寫入int cnt = 0;while(1){//緩沖區char message[MAX];//向緩沖區里寫snprintf(message,sizeof(message),"hello father I am child my pid:%d cnt:%d ", getpid(),cnt);cnt++;//向管道寫write(pipefd[1],message,strlen(message));//跳出if(cnt > 3) break;// char c = 'a';// write(pipefd[1], &c, 1);// cnt++;// cout << "write ....: " << cnt << endl;}//關閉寫端close(pipefd[1]);exit(0);}//父進程要做的事close(pipefd[1]); //關閉寫的通道//從管道中讀取數據char buffer[MAX];while(true){//sleep(2); //睡眠2秒ssize_t n = read(pipefd[0],buffer,sizeof(buffer));if(n > 0){cout << getpid() << "," << "chid say :" << buffer << "to me" << endl;}cout<<"father return value:"<< n << endl;sleep(1);}//回收子進程pid_t rid = waitpid(id,nullptr,0);if(rid == id){cout<<"wait success"<<endl;}return 0;
}

在這里插入圖片描述
這樣表示:寫端關閉,讀端一直讀取, 讀端會讀到read返回值為0, 表示讀到文件結尾

同時注意,進程退出,管道自動關閉

寫端一直寫,讀端關閉

#include<iostream>
#include<unistd.h>
#include<cassert>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<string.h>
using namespace std;
#define MAX 1024int main()
{//建立管道int pipefd[2] = {0};int n = pipe(pipefd);assert(n == 0);//創建子進程pid_t id = fork();//子進程if(id < 0){perror("fork fail");return 1;}if(id ==0){//子進程要做的事close(pipefd[0]); //關閉讀的通道//向管道寫入int cnt = 0;while(true){//緩沖區char message[MAX];//向緩沖區里寫snprintf(message,sizeof(message),"hello father I am child my pid:%d cnt:%d ", getpid(),cnt);cnt++;//向管道寫write(pipefd[1],message,strlen(message));sleep(1);//跳出//if(cnt > 3) break;// char c = 'a';// write(pipefd[1], &c, 1);// cnt++;// cout << "write ....: " << cnt << endl;sleep(1);}//關閉寫端//close(pipefd[1]);exit(0);}//父進程要做的事close(pipefd[1]); //關閉寫的通道//從管道中讀取數據char buffer[MAX];while(true){//sleep(2); //睡眠2秒ssize_t n = read(pipefd[0],buffer,sizeof(buffer));if(n > 0){cout << getpid() << "," << "chid say :" << buffer << "to me" << endl;}cout<<"father return value:"<< n << endl;sleep(1);//直接跳出break;}//關閉讀端close(pipefd[0]);sleep(5);int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid == id){cout << "wait success, child exit sig: " << (status&0x7F) << endl;}// //回收子進程// pid_t rid = waitpid(id,nullptr,0);// if(rid == id)// {//    cout<<"wait success"<<endl;// }return 0;
}

我們得到一下它的信號:
在這里插入圖片描述
我們查一下13號信號:
在這里插入圖片描述
13號信號是:SIGPIPE:

SIGPIPE 是在進程向一個已經被關閉的管道(或者其他的類似的通信方式)寫入數據時,內核向該進程發送的信號。這個信號的默認行為是終止進程。
常見的場景是,一個進程向另一個進程通過管道發送數據,但接收數據的進程提前退出,導致寫入數據的進程嘗試往已關閉的管道寫入數據。在這種情況下,內核會發送 SIGPIPE 信號給寫入數據的進程,通知它目標進程已經退出,不再接收數據。

所以我們才有上述現象。

總結一下管道有4種情況:

管道的4種情況

  1. 正常情況,如果管道沒有數據了,讀端必須等待,直到有數據為止(寫端寫入數據了)
  2. 正常情況,如果管道被寫滿了,寫端必須等待,直到有空間為止(讀端讀走數據)
  3. 寫端關閉,讀端一直讀取, 讀端會讀到read返回值為0, 表示讀到文件結尾
  4. 讀端關閉,寫端一直寫入,OS會直接殺掉寫端進程,通過想目標進程發送SIGPIPE(13)信號,終止目標進程

5種特性:

管道的5種特性

  1. 匿名管道,可以允許具有血緣關系的進程之間進行進程間通信,常用與父子,僅限于此
  2. 匿名管道,默認給讀寫端要提供同步機制 — 了解現象就行
  3. 面向字節流的 — 了解現象就行
  4. 管道的生命周期是隨進程的
  5. 管道是單向通信的,半雙工通信的一種特殊情況

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/712870.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/712870.shtml
英文地址,請注明出處:http://en.pswp.cn/news/712870.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

bert 相似度任務訓練,簡單版本

目錄 任務 代碼 train.py predit.py 數據 任務 使用 bert-base-chinese 訓練相似度任務&#xff0c;參考&#xff1a;微調BERT模型實現相似性判斷 - 知乎 參考他上面代碼&#xff0c;他使用的是 BertForNextSentencePrediction 模型&#xff0c;BertForNextSentencePred…

thinkphp學習10-數據庫的修改刪除

數據修改 使用 update()方法來修改數據&#xff0c;修改成功返回影響行數&#xff0c;沒有修改返回 0 public function index(){$data [username > 孫悟空1,];return Db::name(user)->where(id,11)->update($data);}如果修改數據包含了主鍵信息&#xff0c;比如 i…

STM32標準庫開發——BKP備份RTC時鐘

備份寄存器BKP(Backup Registers) 由于RTC與BKP關聯性較高&#xff0c;所以RTC的時鐘校準寄存器以及一些功能都放在了BKP中。TAMPER引腳主要用于防止芯片數據泄露&#xff0c;可以設計一個機關當TAMPER引腳發生電平跳變時自動清除寄存器內數據不同芯片BKP區別&#xff0c;主要體…

c++入門(2)

上期我們說到了部分c修補C語言的不足&#xff0c;今天我們將剩下的一一說清楚。 函數重載 (1).函數重載的形式 C語言不允許函數名相同的同時存在&#xff0c;但是C允許同名函數存在&#xff0c;但是有要求&#xff1a;函數名相同&#xff0c;參數不同&#xff0c;構成函數重…

【數據結構-圖論】并查集

并查集&#xff08;Union-Find&#xff09;是一種數據結構&#xff0c;它提供了處理一些不交集的合并及查詢問題的高效方法。并查集主要支持兩種操作&#xff1a; 查找&#xff08;Find&#xff09;&#xff1a;確定某個元素屬于哪個子集&#xff0c;這通常意味著找到該子集的…

vue購物車實戰

1.引入vue <script src"https://cdn.jsdelivr.net/npm/vue2.7.14/dist/vue.js"></script> 2.設置高亮部分的樣式 <style> table tr{text-align: center;}.skyblue{background-color: skyblue;}</style> 3.設置body的基本樣式 <div id&q…

人大金倉與mysql的差異與替換

人大金倉中不能使用~下面的符號&#xff0c;字段中使用”&#xff0c;無法識別建表語句 創建表時語句中只定義字段名.字段類型.是否是否為空 Varchar類型改為varchar&#xff08;長度 char&#xff09; Int(0) 類型為int4 定義主鍵&#xff1a;CONSTRAINT 鍵名 主鍵類型&#x…

Found option without preceding group in config file 問題解決

方法就是用記事本打開 然后 左上角點擊 文件 有另存為 就可以選擇編碼格式

Linux設置程序任意位置執行(設置環境變量)

問題 直接編譯出來的可執行程序在執行時需要寫出完整路徑比較麻煩&#xff0c;設置環境變量可以實現在任意位置直接運行。 解決 1.打開.bashrc文件 vim ~/.bashrc 2.修改該文件&#xff08;實現將/home/zhangziheng/file/seqrequester/build/bin&#xff0c;路徑下的可執…

文件流【文件輸入流】

文件流&#xff1a;使用文件輸入流讀取文件中的數據&#xff1a; public class FISDemo {public static void main(String[] args) throws IOException {//將fos.dat文件中的字節讀取回來/*fos.dat文件中的數據:00000001 00000010*/FileInputStream fis new FileInputStream(…

第六節:Vben Admin權限-后端控制方式

系列文章目錄 第一節:Vben Admin介紹和初次運行 第二節:Vben Admin 登錄邏輯梳理和對接后端準備 第三節:Vben Admin登錄對接后端login接口 第四節:Vben Admin登錄對接后端getUserInfo接口 第五節:Vben Admin權限-前端控制方式 文章目錄 系列文章目錄前言一、角色權限(后端…

Java面試題總結6

Spring中有哪些設計模式 簡單工廠&#xff1a;由一個工廠類根據傳入的參數&#xff0c;動態決定應該創建哪一個產品類 工廠方法&#xff1a;實現FactoryBean接口的bean是一類叫做factory的bean 單例模式&#xff1a;保證一個類僅有一個實例&#xff0c;并提供一個訪問它的全…

【辦公類-18-03】(Python)中班米羅可兒證書批量生成打印(班級、姓名)

作品展示——米羅可兒證書打印幼兒姓名 背景需求 2024年3月1日&#xff0c;中4班孩子一起整理美術操作材料《米羅可兒》的操作本——將每一頁紙撕下來&#xff0c;分類擺放、確保紙張上下位置正確。每位孩子們都非常厲害&#xff0c;不僅完成了自己的一本&#xff0c;還將沒有…

C++數據結構與算法——二叉搜索樹的屬性

C第二階段——數據結構和算法&#xff0c;之前學過一點點數據結構&#xff0c;當時是基于Python來學習的&#xff0c;現在基于C查漏補缺&#xff0c;尤其是樹的部分。這一部分計劃一個月&#xff0c;主要利用代碼隨想錄來學習&#xff0c;刷題使用力扣網站&#xff0c;不定時更…

C++編程面試復盤:數組降重+快排+函數指針+類模板

面試真題 真題1 #include <iostream> // 在函數 find_repetnum 的參數列表中&#xff0c;int& length 中的 & 符號表示引用。通過將 length 聲明為引用&#xff0c;函數可以修改傳入的 length 變量的值&#xff0c;并且這種修改會在函數外部生效。 void find_r…

Vue2:路由history模式的項目部署后頁面刷新404問題處理

一、問題描述 我們把Vue項目的路由模式&#xff0c;設置成history 然后&#xff0c;build 并把dist中的代碼部署到nodeexpress服務中 訪問頁面后&#xff0c;刷新頁面報404問題 二、原因分析 server.js文件 會發現&#xff0c;文件中配置的路徑沒有Vue項目中對應的路徑 所以…

React withRouter的使用及源碼實現

一 基本介紹 作用&#xff1a; 把不是通過路由切換過來的組件中&#xff0c;將react-router 的 history、location、match 三個對象傳入props對象上。比如首頁&#xff01; 默認情況下必須是經過路由匹配渲染的組件才存在this.props&#xff0c;才擁有路由參數&#xff0c;才能…

嵌入式學習筆記Day27

今天主要學習了進程間的通信&#xff0c;主要學習了通過管道進行通信 一、進程間的通信 進程間的通信方式有以下幾種&#xff1a; 1.管道 2.信號 3.消息隊列 4.共享內存 5.信號燈 6.套接字二、管道 2.1無名管道 無名管道只能用于具有親緣關系的進程間通信 函數接口&#x…

Nacos進階

目錄 Nacos支持三種配置加載方案 Namespace方案 DataID方案 Group方案 同時加載多個配置集 Nacos支持三種配置加載方案 Nacos支持“Namespacegroupdata ID”的配置解決方案。 詳情見&#xff1a;Nacos config alibaba/spring-cloud-alibaba Wiki GitHub Namespace方案…

《TCP/IP詳解 卷一》第12章 TCP初步介紹

目錄 12.1 引言 12.1.1 ARQ和重傳 12.1.2 滑動窗口 12.1.3 變量窗口&#xff1a;流量控制和擁塞控制 12.1.4 設置重傳的超時值 12.2 TCP的引入 12.2.1 TCP服務模型 12.2.2 TCP可靠性 12.3 TCP頭部和封裝 12.4 總結 12.1 引言 關于TCP詳細內容&#xff0c;原書有5個章…