4.應用層自定義協議與序列化

1.應用層

程序員寫的一個個解決我們實際問題, 滿足我們日常需求的網絡程序, 都是在應用層

1.1再談“協議”

協議是一種 "約定". socket api 的接口, 在讀寫數據時, 都是按 "字符串" 的方式來發送接收的. 如果我們要傳輸一些 "結構化的數據" 怎么辦呢?
其實,協議就是雙方約定好的結構化的數據
約定方案
? 定義結構體來表示我們需要交互的信息; 
? 發送數據時將這個結構體按照一個規則轉換成字符串, 接收到數據的時候再按
照相同的規則把字符串轉化回結構體; 
? 這個過程叫做 "序列化" 和 "反序列化"

1.2序列化 和 反序列化

只要保證, 一端發送時構造的數據, 在另一端能夠正確的進行解析, 就是 ok 的. 
這種約定, 就是 應用層協議。
? 我們要引入序列化和反序列化,我們直接采用現成的方案 -- jsoncpp庫? 我們要對 socket 進行字節流的讀取處理

?從現在起:如果我們要進行網絡協議式的通信,在應用層,強烈建議使用序列化和反序列化的方案。至于直接傳結構體的方案,除非特殊場景,否則不建議

序列化和反序列化的優點是解耦!!!

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

2.1 全雙工

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

結論:

1. write,read 就是收發消息 ---? write和read是不是把數據發送到了網絡中?(no,主要進行的是數據拷貝)(OS把數據發送到網絡中,本質也是拷貝)

2. 主機間通信的本質:把發送方的發送緩沖區內部的數據,拷貝到對端的接受緩沖區!

3. 為什么TCP通信的時候,是全雙工的?因為有兩對發送和接受緩沖區!!!

2.2 面向數據流/面向數據報

?面向數據流(TCP)理解:一次可能讀取1.5,0.5 ....個段數據,TCP 能保證字節流的完整性(無丟失、無重復),但不保證消息邊界的完整性

而 面向數據報(UDP)每個數據報(Datagram)是獨立的 “消息”,包含完整的源 / 目的地址

3.網絡版計算器實現

問題:因為TCP是面向字節流的

當讀取方在讀取的時候,可能讀到一個完整的json請求,也可能會讀到半個?一個半?5個?5個半請求json串?? --- 全都有可能發生。

read -> 本身并不保證讀到的報文的完整性!!!他只保證把數據如果有,就讀上來(誰來保證呢??由應用層程序員自己保證!!)【進一步定制協議...】

當我們tcp中讀取數據的時候,讀到的報文不完整,或者多讀了,導致下一個報文不完整了,這個問題叫做 “粘包” 問題?

?Common.hpp

?InetAddr.hpp

?Log.hpp

?main.cc

?makefile

?Mutex.hpp

?NetCal.hpp

?Protocol.hpp

?Socket.hpp

?TcpClient.cc

?TcpServer.hpp

Deamon.hpp

4.關于流式數據的處理

5.進程間關系與守護進程

5.1 進程組

之前我們提到了進程的概念, 其實每一個進程除了有一個進程 ID(PID)之外 還屬于一
個進程組。進程組是一個或者多個進程的集合, 一個進程組可以包含多個進程。 每一
個進程組也有一個唯一的進程組 ID(PGID), 并且這個 PGID 類似于進程 ID, 同樣是
一個正整數, 可以存放在 pid_t 數據類型中。

5.1.2 組長進程

每一個進程組都有一個組長進程。 組長進程的 ID 等于其進程 ID。我們可以通過 ps
令看到組長進程的現象
Shell
[node@localhost code]$ ps -o pid,pgid,ppid,comm | cat
# 輸出結果
PID PGID PPID COMMAND
2806 2806 2805 bash
2880 2880 2806 ps
2881 2880 2806 cat
???進程組組長的作用: 進程組組長可以創建一個進程組或者創建該組中的進程
???進程組的生命周期: 從進程組創建開始到其中最后一個進程離開為止。注意: 主要某個進程組中有一個進程存在, 則該進程組就存在, 這與其組長進程是否已經終止無關。

5.2 會話

會話其實和進程組息息相關,會話可以看成是一個或多個進程組的集合, 一個會話可以包含多個進程組。每一個會話也有一個會話 ID(SID)(通常我們都是使用管道將幾個進程編成一個進程組
5.2.2 如何創建會話
可以調用 setseid 函數來創建一個會話, 前提是調用進程不能是一個進程組的組長
C
#include <unistd.h>
/*
*功能:創建會話
*返回值:創建成功返回 SID, 失敗返回-1
*/
pid_t setsid(void);
該接口調用之后會發生:
調用進程會變成新會話的會話首進程。 此時, 新會話中只有唯一的一個進 程
調用進程會變成進程組組長。 新進程組 ID 就是當前調用進程 ID
該進程沒有控制終端。 如果在調用 setsid 之前該進程存在控制終端, 則調用之后會切斷聯系
需要注意的是: 這個接口如果調用進程原來是進程組組長, 則會報錯, 為了避免這種情況, 我們通常的使用方法是先調用 fork 創建子進程, 父進程終止, 子進程繼續執行, 因為子進程會繼承父進程的進程組 ID, 而進程 ID 則是新分配的, 就不會出現錯誤的情況。

?

?5.2.2 setsid

setsid是一個非常重要的系統調用和命令行工具,主要用于創建新的會話(session)和進程組(process group)

5.3 控制終端

UNIX 系統中,用戶通過終端登錄系統后得到一個 Shell 進程,這個終端成為 Shell
進程的控制終端。控制終端是保存在 PCB 中的信息,我們知道 fork 進程會復制 PCB
中的信息,因此由 Shell 進程啟動的其它進程的控制終端也是這個終端。默認情況下
沒有重定向,每個進程的標準輸入、標準輸出和標準錯誤都指向控制終端,進程從標
準輸入讀也就是讀用戶的鍵盤輸入,進程往標準輸出或標準錯誤輸出寫也就是輸出到
顯示器上。另外會話、進程組以及控制終端還有一些其他的關系:
一個會話可以有一個控制終端,通常會話首進程打開一個終端(終端設備或
偽終端設備)后,該終端就成為該會話的控制終端。
建立與控制終端連接的會話首進程被稱為控制進程
一個會話中的幾個進程組可被分成一個前臺進程組以及一個或者多個后臺進
程組
如果一個會話有一個控制終端,則它有一個前臺進程組,會話中的其他進程
組則為后臺進程組。
無論何時進入終端的中斷鍵(ctrl+c)或退出鍵(ctrl+\),就會將中斷信號
發送給前臺進程組的所有進程。
如果終端接口檢測到調制解調器(或網絡)已經斷開,則將掛斷信號發送給
控制進程(會話首進程)。
這些特性的關系如下圖所示:

5.4 作業控制

作業是針對用戶來講,用戶完成某項任務而啟動的進程,一個作業既可以只包含一個進程,也可以包含多個進程,進程之間互相協作完成任務, 通常是一個進程管道。
Shell 分前后臺來控制的不是進程而是作業 或者進程組。一個前臺作業可以由多個進程組成,一個后臺作業也可以由多個進程組成,Shell 可以同時運?一個前臺作業和任意多個后臺作業,這稱為作業控制

5.4.2 作業的掛起與切回

(1) 作業掛起
我們在執?某個作業時,可以通過 Ctrl+Z 鍵將該作業掛起,然后 Shell 會顯示相關的作業號、狀態以及所執?的命令信息。現通過 Ctrl+Z 將作業掛起, 該作業狀態已經變為了停止狀態
(2) 作業切回
如果想將掛起的作業切回,可以通過 fg 命令,fg 后面可以跟作業號作業的命令名稱。如果參數缺省則會默認將作業號為 1 的作業切到前臺來執?,若當前系統只有一個作業在后臺進?,則可以直接使用 fg 命令不帶參數直接切回

5.4.3 查看后臺執行或掛起的作業

我們可以直接通過輸入 jobs 命令查看本用戶當前后臺執?或掛起的作業
???參數-l 則顯示作業的詳細信息
???參數-p 則只顯示作業的 PID
例如, 我們先在后臺及前臺運?兩個作業, 并將前臺作業掛起, 來用 jobs 命令
查看作業相關的信息:
Shell
# 在后臺運行一個作業 sleep
[node@localhost code]$ sleep 300 &
# 運行剛才的死循環可執行程序
[node@localhost code]$ ./test
# 鍵入 Ctrl + Z 掛起作業
# 使用 jobs 命令查看后臺及掛起的作業
[node@localhost code]$ jobs -l運?結果如下所示:
Shell
# 結果依次對應作業號 默認作業 作業狀態 運行程序信息
[1]- 2265 運行中 sleep 300 &
[2]+ 2267 停止 ./test7

5.4.4?作業控制相關的信號

鍵入 Ctrl + Z 可以將前臺作業掛起,實際上是將 STGTSTP 信號發送至前臺進程組作業中的所有進程, 后臺進程組中的作業不受影響。 在 unix系統中, 存在 3 個特殊字符可以使得終端驅動程序產生信號, 并將信號發送至前臺進程組作業, 它們分別是:
? Ctrl + C: 中斷字符, 會產生 SIGINT 信號
? Ctrl + \: 退出字符, 會產生 SIGQUIT 信號
? Ctrl + Z:掛起字符, 會產生 STGTSTP 信號
終端的 I/O(即標準輸入和標準輸出)和終端產生的信號總是從前臺進程組作業連接打破實際終端

5.5 守護進程

附錄:
1. Jsoncpp

命令?ls /usr/include/jsoncpp/json/?用于查看 Linux 系統中?JSONCpp 庫的頭文件目錄

?Jsoncpp 是一個用于處理 JSON 數據的 C++ 庫。它提供了將 JSON 數據序列化為字符串以及從字符串反序列化為 C++ 數據結構的功能

C++
ubuntu:sudo apt-get install libjsoncpp-dev
Centos: sudo yum install jsoncpp-devel
Jsoncpp 提供了多種方式進行序列化:
1.?使用 Json::Value toStyledString 方法:
????????○ 優點:將 Json::Value 對象直接轉換為格式化的 JSON 字符串
C++
#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 更快,因為它不添加額外的空格和換行符。
C++
#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" : "男"
}

2. 反序列化

1. 使用 Json::Reader
????????○ 優點:提供詳細的錯誤信息和位置,方便調試。
C++
#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: 北京

3. Json::Value

Json::Value Jsoncpp 庫中的一個重要類,用于表示和操作 JSON 數據結構。以下是一些常用的 Json::Value 操作列表(具體的看課件)

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

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

相關文章

【QT搭建opencv環境】

本文參考以下文章&#xff1a; https://blog.csdn.net/weixin_43763292/article/details/112975207 https://blog.csdn.net/qq_44743171/article/details/124335100 使用軟件 QT 5.14.2下載地址&#xff1a;download.qt.io 選擇版本&#xff1a;Qt 5.14.2 Qt 5.14.2百度網盤鏈接…

golang--函數棧

一、函數棧的組成結構&#xff08;棧幀&#xff09; 每個函數調用對應一個棧幀&#xff0c;包含以下核心部分&#xff1a; 1. 參數區 (Arguments) 位置&#xff1a;棧幀頂部&#xff08;高地址端&#xff09;內容&#xff1a; 函數調用時傳入的參數按從右向左順序壓棧&#xff…

【FAQ】創建Dynamics 365 Sales環境

參考文章&#xff1a;5 分鐘內安裝 Dynamics 365 Sales 步驟 1&#xff1a;訪問 Power Platform 管理中心 導航到make.powerapps.com&#xff0c;然后點擊右上角的齒輪圖標。選擇管理中心&#xff0c;或者訪問aka.ms/ppac訪問 Power Platform 管理中心。 第 2 步&#xff1a…

【數據庫】使用Sql Server將分組后指定字段的行數據轉為一個字段顯示,并且以逗號隔開每個值,收藏不迷路

大家好&#xff0c;我是全棧小5&#xff0c;歡迎來到《小5講堂》。 這是《Sql Server》系列文章&#xff0c;每篇文章將以博主理解的角度展開講解。 溫馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不對之處望指正&#xff01; 目錄前言示例數據集數…

7.項目起步(1)

1&#xff0c;項目起步-初始化項目并使用git管理創建項目并精細化配置src目錄調整git 管理項目2項目起步-配置別名路徑聯想提示什么是別名路徑聯想提示如何進行配置 &#xff08;自動配置了&#xff09;{"compilerOptions" : {"baseUrl" : "./",…

【C++詳解】深入解析繼承 類模板繼承、賦值兼容轉換、派生類默認成員函數、多繼承與菱形繼承

文章目錄一、繼承概念二、繼承定義定義格式繼承后基類成員訪問方式的變化類模板的繼承三、基類和派?類間的轉換(賦值兼容轉換)四、繼承中的作用域隱藏規則兩道筆試常考題五、派生類的默認成員函數四個常見默認成員函數實現?個不能被繼承的類六、繼承與友元七、繼承與靜態成員…

加法器 以及ALU(邏輯算術單元)

加法器框架&#xff0c;首先介紹原理&#xff0c;然后引入一位加法器最后再引入多位加法器最后引入帶符號的加法器這一節涉及到的硬件電路的知識理解就好&#xff0c;實在看不懂就跳過&#xff0c;但是封裝以后的功能必須看懂。這是一個一般的加法過程涉及到的必要元素圖中已經…

設計模式實戰:自定義SpringIOC(親手實踐)

上一篇&#xff1a;設計模式實戰&#xff1a;自定義SpringIOC&#xff08;理論分析&#xff09; 自定義SpringIOC&#xff08;親手實踐&#xff09; 上一篇文章&#xff0c;我們介紹了SpringIOC容器的核心組件及其作用&#xff0c;下面我們來動手仿寫一個SpringIOC容器&#…

力扣面試150(42/150)

7.28 20. 有效的括號 給定一個只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判斷字符串是否有效。 有效字符串需滿足&#xff1a; 左括號必須用相同類型的右括號閉合。左括號必須以正確的順序閉合。每個右括號都有一…

基于黑馬教程——微服務架構解析(二):雪崩防護+分布式事務

之前的兩篇文章我們介紹了微服務的基礎概念及其服務間通信機制。本篇將深入探討微服務的核心保障&#xff1a;服務保護與分布式事務。一、微服務保護問題描述&#xff1a; 在一個購物車的微服務中&#xff0c;倘若某一項服務&#xff08;服務A&#xff09;同一時刻訪問的數據十…

LeetCode: 429 N叉樹的層序遍歷

題目描述給定一個 N 叉樹&#xff0c;返回其節點值的層序遍歷&#xff08;即從左到右&#xff0c;逐層訪問每一層的所有節點&#xff09;。示例輸入格式&#xff08;層序序列化&#xff09;&#xff1a;輸入示意&#xff1a;1/ | \3 2 4/ \5 6輸出&#xff1a;[[1], [3,2,4…

使用phpstudy極簡快速安裝mysql

使用 phpStudy 極簡快速安裝 MySQL 的完整指南&#xff1a; 一、phpStudy 簡介 phpStudy 是一款 Windows 平臺下的 PHP 環境集成包&#xff0c;包含&#xff1a; Apache/Nginx PHP 5.x-7.x MySQL 5.5-8.0 phpMyAdmin 二、安裝步驟 1. 下載安裝包 訪問官網下載&#xf…

git lfs使用

apt install git lfs 或者下載二進制文件加到環境變量 https://github.com/git-lfs/git-lfs/releases git lfs install git lfs clone huggingface文件路徑 如果訪問不了hugggingface.co用hf-mirror.com替代&#xff0c;國內下載速度還是挺快的 先按照pip install modelscope m…

6、CentOS 9 安裝 Docker

&#x1f433; CentOS 9 安裝 Docker 最全圖文教程&#xff08;含鏡像源優化與常見問題解決&#xff09;標簽&#xff1a;CentOS 9、Docker、容器技術、開發環境、國內鏡像源 適合讀者&#xff1a;后端開發、運維工程師、Linux 初學者&#x1f4cc; 前言 在 CentOS 9 上安裝 Do…

SystemV消息隊列揭秘:原理與實戰

目錄 一、消息隊列的基本原理 1、基本概念 2、基本原理 3、消息類型的關鍵作用 4、重要特性總結 5、生命周期管理 6、典型應用場景 二、System V 消息隊列的內核數據結構 1、消息隊列的管理結構 msqid_ds&#xff08;消息隊列標識符結構&#xff09; 關鍵字段解析 2…

5 分鐘上手 Firecrawl

文章目錄Firecrawl 是什么&#xff1f;本地部署驗證mcp安裝palyground&#x1f525; 5 分鐘上手 FirecrawlFirecrawl 是什么&#xff1f; 一句話&#xff1a; 開源版的 “最強網頁爬蟲 清洗引擎” ? 自動把任意網頁 → 結構化 Markdown / JSON ? 支持遞歸整站抓取、JS 渲染…

算法訓練營day31 貪心算法⑤56. 合并區間、738.單調遞增的數字 、968.監控二叉樹

貪心算法的最后一篇博客&#xff01;前面兩道題都是比較簡單的思路&#xff0c;重點理解一下最后一道題即可。有一說一&#xff0c;進入到貪心算法這一章節之后&#xff0c;我的博客里和代碼注釋里的內容明顯少了很多&#xff0c;因為很多貪心的題目我覺得不需要很復雜的文字說…

Jenkins流水線部署+webhook2.0

文章目錄1. 環境2. 用到的插件3. 流水線部署腳本1. 環境 Centos7Jenkins2.5.0JDKopen17阿里云倉庫 注意&#xff1a;這個版本兼容需要特別注意&#xff0c;要不然會很麻煩 2. 用到的插件 Generic Webhook Trigger 3. 流水線部署腳本 兼容鉤子部署&#xff08;webhook&…

IDM下載失敗排查

網絡連接問題排查檢查網絡連接是否穩定&#xff0c;確保能夠正常訪問互聯網 測試其他下載工具或瀏覽器是否能夠正常下載 嘗試關閉防火墻或殺毒軟件&#xff0c;排除安全軟件攔截的可能性代理和VPN設置檢查確認IDM的代理設置是否正確&#xff0c;是否與系統代理一致 檢查是否使用…

Anaconda安裝時的幾個操作

一、安裝Anaconda 其實Anaconda的安裝比較簡單&#xff0c;點擊next就好了。在安裝中需要注意以下兩點&#xff1a; 1、選擇安裝路徑 在安裝時&#xff0c;路徑最好選擇非C盤&#xff0c;且路徑中不要出現中文&#xff0c;以免后期運行代碼時出現不必要的錯誤。 我安裝時&…