Linux網絡_應用層自定義協議與序列化_守護進程

一.協議

協議是一種 "約定". socket api 的接口, 在讀寫數據時, 都是按 "字符串" 的方式來發送接 收的. 如果我們要傳輸一些 "結構化的數據" 怎么辦呢? 其實,協議就是雙方約定好的結構化的數據

像下面,兩端都知道數據結構data的結構,我們可以直接傳data數據的二進制嗎?

理論可以,但如果兩邊平臺不同,不兼容等導致出錯。

eg.大小端問題 64位指針大小8 32位指針大小4

所以我們一般不通過二進制協議進行傳輸

所以我們一個怎么處理更復雜的、結構化的數據的傳輸呢?

二.序列化和反序列化

1.什么是序列化 反序列化

比如說我們傳一個結構體data,里面包含 int x,char oper ,int y。

我們不要一個一個傳,可以把成員元素整合成一個字符串,再傳。這個就是序列化

但當我們獲取到了這個字符串,怎么獲取到里面包含的消息呢?

我們可以自己進行規定,每個元素間用空格進行隔開,依次進行獲取。

根據制定的規則進行解包,獲取元素,就是反序列化。

序列化: 你將結構體的各個成員轉換成某種格式的字符串,以便傳輸或存儲。例如,使用空格分隔成員。
反序列化: 接收端根據預定的規則解析字符串,并將其恢復為原始數據結構(結構體、對象等)。

2.JSON 序列化

Jsoncpp 是一個用于處理 JSON 數據的 C++ 庫。它提供了將 JSON 數據序列化為字
符串以及從字符串反序列化為 C++ 數據結構的功能。Jsoncpp 是開源的,廣泛用于各
種需要處理 JSON 數據的 C++ 項目中。

序列化方法:

1.使用 Json::Value 的 toStyledString 序列化:

優點:將 Json::Value 對象直接轉換為格式化的 JSON 字符串

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>
int main()
{Json::Value root;root["name"] = "joe";root["sex"] = "男";std::string s = root.toStyledString();std::cout << s << std::endl;return 0;
}
$ . / test.exe
{
"name" : "joe",
"sex" : "男"
}

2.使用 Json::StreamWriter:

優點:提供了更多的定制選項,如縮進、換行符等。

#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include <jsoncpp/json/json.h>
int main()
{Json::Value root;root["name"] = "joe";root["sex"] = "男";Json::StreamWriterBuilder wbuilder; // StreamWriter 的工廠std::unique_ptr<Json::StreamWriter> writer(wbuilder.newStreamWriter());std::stringstream ss;writer->write(root, &ss);std::cout << ss.str() << std::endl;return 0;
}
$ . / test.exe
{
"name" : "joe",
"sex" : "男"
}

3.使用 Json::FastWriter:

比 StyledWriter 更快,因為它不添加額外的空格和換行符。

#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include <jsoncpp/json/json.h>
int main()
{Json::Value root;root["name"] = "joe";root["sex"] = "男";Json::FastWriter writer;std::string s = writer.write(root);std::cout << s << std::endl;return 0;
}
$ . / test.exe
{ "name":"joe","sex" : "男" }#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include <jsoncpp/json/json.h>
int main()
{Json::Value root;root["name"] = "joe";root["sex"] = "男";// Json::FastWriter writer;Json::StyledWriter writer;std::string s = writer.write(root);std::cout << s << std::endl;return 0;
}
$ . / test.exe
{
"name" : "joe",
"sex" : "男"
}

反序列化方法:

使用 Json::Reader:

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>
int main() {// JSON 字符串std::string json_string = "{\"name\":\"張三\",\"age\":30, \"city\":\"北京\"}";// 解析 JSON 字符串Json::Reader reader;Json::Value root;// 從字符串中讀取 JSON 數據             序列化的字符串 進行反序列bool parsingSuccessful = reader.parse(json_string,root);if (!parsingSuccessful) {// 解析失敗,輸出錯誤信息std::cout << "Failed to parse JSON: " <<reader.getFormattedErrorMessages() << std::endl;return 1;}// 訪問 JSON 數據std::string name = root["name"].asString();int age = root["age"].asInt();std::string city = root["city"].asString();// 輸出結果std::cout << "Name: " << name << std::endl;std::cout << "Age: " << age << std::endl;std::cout << "City: " << city << std::endl;return 0;
}
$ . / test.exe
Name : 張三
Age : 30
City : 北京

訪問 JSON 數據,int age = root["age"].asInt(); 如果是char c=root["age"].asInt(),也是用.asInt,沒有.aschar。因為char類型就是整數

三.重新理解 read、write、recv、send 和 tcp 為什么支持全雙工

全雙工:通信雙方可以同時進行雙向數據傳輸。也就是說,發送和接收可以在同一時刻發生。

在任何一臺主機上,TCP 連接既有發送緩沖區,又有接受緩沖區,所以,在內核
中,可以在發消息的同時,也可以收消息,即全雙工。
這就是為什么一個 tcp sockfd 讀寫都是它的原因。
實際數據什么時候發,發多少,出錯了怎么辦,由 TCP 控制,所以 TCP 叫做傳輸控制協議。

在系統內部都有大量的報文,一部分是從發送緩沖區進行傳輸,另一部分是向接收緩沖區進行傳輸。如何進行管理,先描述,再組織。每個報頭間用鏈表進行連接。

在socket結構中就包含兩個隊列,分別是發送隊列,接收隊列,對這兩部份報頭進行管理。

這兩個隊列分別用于存儲發送和接收的報文頭。每個隊列可以通過鏈表來管理報文的順序。

發送緩沖區和發送隊列:發送緩沖區的內容一般是按照隊列的順序被處理的。數據首先進入發送隊列(即緩沖區),然后按順序被發送到遠程主機。在TCP協議中,發送隊列不僅僅是一個簡單的隊列,還會涉及到流量控制、擁塞控制等機制,確保發送方的速度不會超過接收方的處理能力。
接收緩沖區和接收隊列:當數據到達本地系統時,接收隊列會存放這些數據。接收隊列的順序和緩沖區管理相結合,確保應用程序能夠以正確的順序讀取到接收到的數據。

四.ps axj 當前系統的進程信息

   PID  PGID   SID TTY      TIME CMD123  123    123 tty1     00:00:01 bash234  123    123 tty1     00:00:00 ps567  567    567 ?        00:00:10 my_process

PID(進程ID):進程的唯一標識符。
PGID(進程組ID):多個進程共享的組ID。(處在同一組的進程PGID相同,一般第一個是組長)
SID(會話ID):進程所屬的會話ID。
TTY(終端):進程關聯的終端(如果有)。
TIME(CPU時間):進程使用的CPU時間。
CMD:啟動該進程的命令。

五.守護進程

1.前臺進程 后臺進程

像在命令行中直接sleep 100 啟動的就是前臺進程,如果在后面加& ,sleep 100 &就把這個進程在后臺啟動。

啟動一個前臺進程(例如,運行 sleep 100),該進程會占用終端。前臺進程會占據整個終端的輸入/輸出流,因此你無法在命令行中執行其他命令(如 ls)直到這個前臺進程完成。

2.fd 任務號 后臺進程->前臺進程

當我們啟動了一個后臺進程,怎么再把它放到前臺呢?

fd+任務號

使用 jobs 命令可以列出當前 shell 會話中所有的后臺任務,并顯示每個任務的任務號(Job ID)和當前狀態。

3.Ctrl+Z bg 任務號?前臺進程->后臺進程

1.ctrl+z 掛起前臺進程,變為暫停狀態。

2.bg+任務號 將掛起的進程放到后臺,不能直接把前臺進程放在后臺。

4.后臺進程和守護進程

當我們進行登錄,系統會創建一個會話,這個會話中bash進程當作前臺進程,與終端直接連接,建立后臺進程不會直接接收用戶的輸入,也不會直接向終端輸出數據,一般不輸入輸出重定向到其它文件。

如果我們退出登錄,該會話的前臺進程 終端都會關閉,里面的后臺進程也會受到影響。

有沒有辦法退出時讓該后端進程不受影響?

把該后端進程放到一個新的會話中,并且持續運行,不與任何終端關聯,就是守護進程。

如何創建守護進程?

手動:

1.調用 fork():首先,進程調用 fork() 創建一個子進程,父進程退出,確保子進程不成為孤兒進程。
2.調用 setsid():子進程通過 setsid() 調用成為新會話的會話領導者,這樣它就不再與控制終端關聯。(不是是進程組的組長調用它。fork()子進程調用)
3.重定向輸入輸出:守護進程會將輸入輸出重定向到日志文件或 /dev/null (文件黑洞 不會保存數據),以確保不會干擾終端。
4.持續運行:守護進程通常進入無限循環,保持持續運行,處理后臺任務。

#pragma once#include <iostream>
#include <cstdlib>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>#define ROOT "/"
#define devnull "/dev/null"void Daemon(bool ischdir, bool isclose)
{// 1. 守護進程一般要屏蔽到特定的異常信號signal(SIGCHLD, SIG_IGN);signal(SIGPIPE, SIG_IGN);// 2. 成為非組長if (fork() > 0)exit(0);// 3. 建立新會話setsid();// 4. 每一個進程都有自己的CWD,是否將當前進程的CWD更改成為 / 根目錄if (ischdir)chdir(ROOT);// 5. 已經變成守護進程啦,不需要和用戶的輸入輸出,錯誤進行關聯了if (isclose){::close(0);::close(1);::close(2);}else{int fd = ::open(devnull, O_WRONLY);if (fd > 0){// 各種重定向dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);close(fd);}}
}

daemon:

int daemon(int nochdir, int noclose);

nochdir:如果為 1,守護進程將不改變當前工作目錄;如果為 0,守護進程會將當前工作目錄更改為根目錄(/),以避免占用一個文件系統的目錄。
noclose:如果為 1,守護進程不會關閉文件描述符。如果為 0,守護進程會關閉標準輸入、標準輸出和標準錯誤輸出文件描述符。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main() {// 將進程轉變為守護進程if (daemon(0, 0) == -1) {perror("daemon");exit(1);}// 守護進程的工作while (1) {// 這里可以添加守護進程執行的任務sleep(10);  // 每10秒執行一次任務}return 0;
}

在原會話的后臺進程會受到終端信號干擾、父進程退出以及會話管理的影響。

通過使用 setsid() 來創建新的會話,守護進程能夠脫離終端和父進程的控制,確保在系統后臺獨立穩定地運行,避免受到干擾。

守護進程處于新的會話:

1.確保進程不被終端信號干擾

在原有會話中運行的進程通常會收到一些終端信號,尤其是當用戶退出時,例如 SIGHUP 信號,通常會導致進程終止。守護進程必須避免這些信號的干擾,才能保證其在系統后臺長時間穩定運行。

調用 setsid() 后,守護進程會脫離原會話,并成為一個新的會話的會話領導者,控制終端不再影響它。這確保了守護進程不會因為終端的關閉或會話的結束而被中斷。

2.防止守護進程成為孤兒進程

在操作系統中,進程分為父進程和子進程。如果一個進程的父進程終止,該進程會被操作系統的 "init" 進程收養,成為孤兒進程。然而,守護進程希望在系統后臺長期運行,它不希望被父進程或任何其他進程“收養”,而是希望有完全的獨立性。

通過調用 setsid(),守護進程脫離了原會話,成為一個新的會話的會話領導者,這樣它不再依賴任何父進程,確保它不會成為孤兒進程,也不會因為父進程的退出而終止。

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

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

相關文章

SQL命令詳解之多表查詢(連接查詢)

目錄 1 簡介 2 內連接查詢 2.1 內連接語法 2.2 內連接練習 3 外連接查詢 3.1 外連接語法 3.2 外連接練習 4 總結 1 簡介 連接的本質就是把各個表中的記錄都取出來依次匹配的組合加入結果集并返回給用戶。我們把 t1 和 t2 兩個表連接起來的過程如下圖所示&#xff1a; …

001-碼云操作

碼云操作 一、配置公鑰1.官網地址1.進入 git bash2.查看生成的公鑰3.設置到 Gitee4.測試 二、初始化一個項目1.新建倉庫 一、配置公鑰 方便后續提交代碼不用填寫密碼 1.官網地址 官網地址&#xff1a;https://gitee.com/Git碼云教程&#xff1a;https://gitee.com/help/arti…

30.[前端開發-JavaScript基礎]Day07-數組Array-高階函數-日期Date-DOM

JavaScript的DOM操作 &#xff08;一&#xff09; 1 什么是DOM&#xff1f; 認識DOM和BOM 深入理解DOM 2 認識DOM Tree DOM Tree的理解 3 DOM的整體結構 DOM的學習順序 DOM的繼承關系圖 document對象 4 節點、元素導航 節點&#xff08;Node&#xff09;之間的導航&…

【自學筆記】Spring基礎知識點總覽-持續更新

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 Spring 基礎知識點總覽1. Spring 框架簡介2. IoC&#xff08;控制反轉&#xff09;與 DI&#xff08;依賴注入&#xff09;2.1 IoC 容器2.2 依賴注入方式示例代碼&a…

WordPress多語言插件GTranslate

GTranslate是一個免費的WordPress多語言插件&#xff0c;它允許您將網站內容翻譯成多種語言。這個插件提供了一個簡單易用的界面&#xff0c;讓您可以在WordPress后臺直接進行翻譯操作。以下是GTranslate插件的一些主要特點&#xff1a; 免費使用&#xff1a;GTranslate插件完…

數列極限入門習題

數列極限入門習題 lim ? n → ∞ ( 1 1 2 1 3 ? 1 n ) 1 n \lim\limits_{n\rightarrow\infty}(1 \frac{1}{2}\frac{1}{3}\cdots\frac{1}{n})^{\frac{1}{n}} n→∞lim?(121?31??n1?)n1? lim ? n → ∞ ( 1 n 1 1 n 2 ? 1 n n ) \lim\limits_{n\rightarrow\…

嵌入式學習前要了解的基礎知識

一、電壓和電流 在嵌入式開發中&#xff0c;電壓和電流是兩個基本的電氣概念&#xff0c;對于理解和設計電子電路至關重要。它們直接影響到嵌入式系統的性能、功耗、可靠性和安全性。 電壓&#xff08;Voltage&#xff09; 電壓是電場力推動電荷移動的能力&#xff0c;通常以…

機器學習:強化學習的epsilon貪心算法

強化學習&#xff08;Reinforcement Learning, RL&#xff09;是一種機器學習方法&#xff0c;旨在通過與環境交互&#xff0c;使智能體&#xff08;Agent&#xff09;學習如何采取最優行動&#xff0c;以最大化某種累積獎勵。它與監督學習和無監督學習不同&#xff0c;強調試錯…

Spring學習筆記03——Spring Boot的文件結構

Spring boot常見的文件結構&#xff1a; src/ ├── main/ │ ├── java/ │ │ └── com.example.demo/ │ │ ├── DemoApplication.java # 主入口 │ │ ├── config/ # 配置類 │ │ ├── controller/ …

談談 HTTPS 的工作原理,SSL / TLS 握手流程是什么?

一、HTTPS 核心機制&#xff1a;非對稱加密 對稱加密 HTTPS HTTP over TLS/SSL&#xff0c;通過 ?混合加密體系? 解決三大問題&#xff1a; ?防竊聽? - 對稱加密傳輸內容&#xff08;如 AES&#xff09;?防篡改? - 數字簽名驗證數據完整性?防冒充? - 數字證書驗證服…

共軛梯度法筆記

一、梯度下降法 x k 1 x k ? α ? f ( x k ) x_{k1} x_k - \alpha \nabla f(x_k) xk1?xk??α?f(xk?) 這是普通的梯度下降公式&#xff0c;有兩個量是關鍵&#xff0c;步長 α \alpha α和方向 ? f ( x k ) \nabla f(x_k) ?f(xk?)。這里的方向直接選擇了梯度方向&…

ubuntu 啟動不起來,光標閃爍 解決方法

ubuntu 啟動不起來&#xff0c;光標閃爍 進不了系統&#xff0c;解決方法 按ctrl alt f2&#xff0c;進入終端&#xff0c;登錄。 jounal -b 查看啟動日志。 發現是找不到顯卡驅動程序。 解決方法&#xff1a; 卸載nvidia程序。 sudo systemctl stop gdm # 適用于GNOME…

CSS - 妙用Sass

官方文檔&#xff1a;https://www.sass.hk/docs/ 1.例1&#xff1a; each $theme in $themeList {$themeKey: map-get($theme, key);media screen and (weex-theme: $themeKey) {.btnText {max-width: 150px;include font(map-get($theme, medFont),map-get($theme, subFontS…

chromadb向量數據庫使用 (2)

目錄 代碼代碼解釋**1. 導入 chatGLM 嵌入函數****2. 創建 ChromaDB 客戶端和集合****3. 查詢集合中的數據數量****4. 添加數據到集合****5. 獲取已存儲的文檔****6. 更新文檔****7. 再次獲取數據&#xff0c;驗證更新結果****8. 刪除某個文檔****9. 獲取已刪除的文檔****總結*…

我的世界1.20.1forge模組開發進階物品(7)——具有動畫、3D立體效果的物品

基礎的物品大家都會做了對吧?包括武器的釋放技能,這次來點難度,讓物品的貼圖呈現動畫效果和扔出后顯示3D立體效果,這個3D立體效果需要先學習blockbench,學習如何制作貼圖。 Blockbench Blockbench是一個用于創建和編輯三維模型的免費軟件,特別適用于Minecraft模型的設計…

大模型在敗血癥預測及圍手術期管理中的應用研究報告

目錄 一、引言 1.1 研究背景與意義 1.2 研究目的與創新點 1.3 研究方法與數據來源 二、敗血癥概述 2.1 定義與流行病學 2.2 病因與發病機制 2.3 臨床表現與診斷標準 2.4 并發癥與危害 三、大模型技術原理及在醫療領域的應用 3.1 大模型技術概述 3.2 大模型在醫療領…

SpringBoot接口自動化測試實戰:從OpenAPI到壓力測試全解析

引言&#xff1a;接口測試的必要性 在微服務架構盛行的今天&#xff0c;SpringBoot項目的接口質量直接影響著系統穩定性。本文將分享如何通過自動化工具鏈實現接口的功能驗證與性能壓測&#xff0c;使用OpenAPI規范打通測試全流程&#xff0c;讓您的接口質量保障體系更加完備。…

微軟具身智能感知交互多面手!Magma:基于基礎模型的多模態AI智能體

作者&#xff1a; Jianwei Yang, Reuben Tan, Qianhui Wu, Ruijie Zheng, Baolin Peng, Yongyuan Liang, Yu Gu, MuCai, SeonghyeonYe, JoelJang, Yuquan Deng, Lars Liden, Jianfeng Gao 單位&#xff1a;微軟研究院&#xff0c;馬里蘭大學&#xff0c;威斯康星大學麥迪遜分校…

Linux中jdk-8u291-linux-x64 中jdk工具包

jdk-8u291-linux-x64 指的是適用于 64 位 Linux 系統的 Java 開發工具包&#xff08;JDK&#xff09;8 更新 291 版本。這是 JDK 的一個特定版本&#xff0c;用于開發 Java 應用程序和小程序。 jdk-8u291-linux-x64 網盤下載鏈接&#xff1a;夸克網盤分享

Baklib云內容中臺的核心架構是什么?

云內容中臺分層架構解析 現代企業內容管理系統的核心在于構建動態聚合與智能分發的云端中樞。以Baklib為代表的云內容中臺采用三層架構設計&#xff0c;其基礎層為數據匯聚工具集&#xff0c;通過標準化接口實現多源異構數據的實時采集與清洗&#xff0c;支持從CRM、ERP等業務…