【Linux網絡】應用層自定義協議與序列化

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

應用層

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

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

其實,協議就是雙方約定好的結構化的數據

網絡版計算器

例如,我們需要實現一個服務器版的加法器.我們需要客戶端把要計算的兩個加數發過去, 然后由服務器進行計算,最后再把結果返回給客戶端.

約定方案一:

  • 客戶端發送一個形如"1+1"的字符串;
  • 這個字符串中有兩個操作數,都是整形;
  • 兩個數字之間會有一個字符是運算符,運算符只能是+;
  • 數字和運算符之間沒有空格;

約定方案二:

  • 定義結構體來表示我們需要交互的信息;
  • 發送數據時將這個結構體按照一個規則轉換成字符串,接收到數據的時候再按照相同的規則把字符串轉化回結構體;
  • 這個過程叫做"序列化"和"反序列化"

序列化和反序列化

在這里插入圖片描述

無論我們采用方案一,還是方案二,還是其他的方案,只要保證,一端發送時構造的數據,在另一端能夠正確的進行解析,就是ok的.這種約定,就是應用層協議

但是,為了讓我們深刻理解協議,打算自定義實現一下協議的過程。

  • 我們采用方案2,我們也要體現協議定制的細節
  • 我們要引入序列化和反序列化,只不過我們課堂直接采用現成的方案–jsoncpp庫
  • 我們要對socket進行字節流的讀取處理

理解read、write、recv、send和tcp支持全雙工

在這里插入圖片描述

所以:

  • 在任何一臺主機上,TCP連接既有發送緩沖區,又有接受緩沖區,所以,在內核中,可以在發消息的同時,也可以收消息,即全雙工

  • 這就是為什么一個tcpsockfd讀寫都是它的原因

  • 實際數據什么時候發,發多少,出錯了怎么辦,由TCP控制,所以TCP叫做傳輸控制協議

Json

Jsoncpp

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

特性

  1. 簡單易用:Jsoncpp提供了直觀的API,使得處理JSON數據變得簡單。
  2. 高性能:Jsoncpp的性能經過優化,能夠高效地處理大量JSON數據。
  3. 全面支持:支持JSON標準中的所有數據類型,包括對象、數組、字符串、數字、布爾值和null。
  4. 錯誤處理:在解析JSON數據時,Jsoncpp提供了詳細的錯誤信息和位置,方便開發者調試。
    當使用Jsoncpp庫進行JSON的序列化和反序列化時,確實存在不同的做法和工具類可供選擇。以下是對Jsoncpp中序列化和反序列化操作的詳細介紹:

安裝

C++

  • ubuntu: sudo apt - get install libjsoncpp - dev
  • Centos: sudo yum install jsoncpp - devel

序列化

序列化指的是將數據結構或對象轉換為一種格式,以便在網絡上傳輸或存儲到文件中。Jsoncpp提供了多種方式進行序列化:

  1. 使用Json::Value的toStyledString方法
    • 優點:將Json::Value對象直接轉換為格式化的JSON字符串。
    • 示例
#include <iostream>
#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;
}

執行結果:

{"name" : "joe","sex" : "男"
}
  1. 使用Json::StreamWriter
    • 優點:提供了更多的定制選項,如縮進、換行符等。
    • 示例
#include <iostream>
#include <string>
#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;
}

執行結果:

{"name" : "joe","sex" : "男"
}
  1. 使用Json::FastWriter
    • 優點:比StyledWriter更快,因為它不添加額外的空格和換行符。
    • 示例
#include <iostream>
#include <string>
#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;
}

執行結果:

{"name":"joe","sex":"男"}

另一種寫法示例:

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

執行結果:

{"name" : "joe","sex" : "男"
}

反序列化

反序列化指的是將序列化后的數據重新轉換為原來的數據結構或對象。Jsoncpp提供了以下方法進行反序列化:

  1. 使用Json::Reader
    • 優點:提供詳細的錯誤信息和位置,方便調試。
    • 示例
#include <iostream>
#include <jsoncpp/json/json.h>int main() {std::string json_string = "{\"name\":\"張三\",\"age\":30,\"city\":\"北京\"}";// 解析JSON字符串Json::Value root;Json::Reader reader;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;
}

執行結果:

Name: 張三
Age: 30
City: 北京
  1. 使用Json::CharReader的派生類(不推薦,上面的足夠了)
    在某些情況下,你可能需要更精細地控制解析過程,可以直接使用Json::CharReader的派生類。
    但通常情況下,使用Json::parseFromString或Json::Reader的parse方法就足夠了。

總結

你可以用toStyledString、StreamWriter和FastWriter提供了不同的序列化選項,它們提供強大的錯誤處理機制。
Json::Reader和parseFromString函數是Jsoncpp中主要的反序列化工具,在進行序列化和反序列化時,請確保處理所有可能的錯誤情況,并驗證輸入和輸出的有效性。

Json::Value

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

  1. 構造函數
    • Json::Value():默認構造函數,創建一個空的Json::Value對象。
    • Json::Value(Json::ValueType type, bool aValue = false):根據給定的類型創建一個Json::Value對象。
  2. 訪問元素
    • Json::Value& operator[](const char key)*:通過鍵(字符串)訪問對象中的元素。如果鍵不存在,則創建一個新的元素。
    • Json::Value& operator[](const std::string& key):同上,但使用std::string類型的鍵。
    • Json::Value& operator[](ArrayIndex index):通過索引訪問數組中的元素。如果索引超出范圍,則創建一個新的元素。
    • Json::Value at(const char key)*:通過鍵訪問對象中的元素,如果鍵不存在則拋出異常。
    • Json::Value at(const std::string& key):同上,但使用std::string類型的鍵。
  3. 類型檢查
    • bool isNull():檢查值是否為null類型。
    • bool isBool():檢查值是否為布爾類型。
    • bool isInt():檢查值是否為32位整數類型。
    • bool isInt64():檢查值是否為64位整數類型。
    • bool isUInt():檢查值是否為無符號整數類型。
    • bool isUInt64():檢查值是否為64位無符號整數類型。
    • bool isIntegral():檢查值是否為整數或可轉換為整數的浮點數。
    • bool isDouble():檢查值是否為雙精度浮點數。
    • bool isNumeric():檢查值是否為數字(整數或浮點數)。
    • bool isString():檢查值是否為字符串。
    • bool isArray():檢查值是否為數組。
    • bool isObject():檢查值是否為對象(即鍵值對的集合)。
  4. 賦值和類型轉換
    • Json::Value& operator=(bool value):將布爾值賦給Json::Value對象。
    • Json::Value& operator=(int value):將32位整數賦給Json::Value對象。
    • Json::Value& operator=(int64_t value):將64位整數賦給Json::Value對象。
    • Json::Value& operator=(uint value):將無符號整數賦給Json::Value對象。
    • Json::Value& operator=(uint64_t value):將64位無符號整數賦給Json::Value對象。
    • Json::Value& operator=(double value):將雙精度浮點數賦給Json::Value對象。
    • Json::Value& operator=(const char value)*:將C字符串賦給Json::Value對象。
    • Json::Value& operator=(const std::string& value):將std::string賦給Json::Value對象。
    • bool asBool():將值轉換為布爾類型(如果可能)。
    • int asInt():將值轉換為32位整數類型(如果可能)。
    • Int64 asInt64():將值轉換為64位整數類型(如果可能)。
    • UInt64 asUInt64():將值轉換為64位無符號整數類型(如果可能)。
    • std::string asString():將值轉換為字符串類型(如果可能)。
  5. 數組和對象操作
    • size_t size():返回數組或對象中的元素數量。
    • bool empty():檢查數組或對象是否為空。
    • void resize(ArrayIndex newSize):調整數組的大小。
    • void clear():刪除數組或對象中的所有元素。
    • void append(const Json::Value& value):在數組末尾添加一個新元素。
    • Json::Value& operator[](const char key, const Json::Value& defaultValue = Json::nullValue)*:在對象中插入或訪問一個元素,如果鍵不存在則使用默認值。
    • Json::Value& operator[](const std::string& key, const Json::Value& defaultValue = Json::nullValue):在對象中插入或訪問一個元素,如果鍵不存在則使用默認值,但使用std::string類型的鍵。

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

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

相關文章

MySQL + Elasticsearch:為什么要使用ES,使用場景與架構設計詳解

MySQL Elasticsearch&#xff1a;為什么要使用ES&#xff0c;使用場景與架構設計詳解 前言一、MySQL Elasticsearch的背景與需求1.1 為什么要使用Elasticsearch&#xff08;ES&#xff09;&#xff1f;1.2 為什么MySQL在某些場景下不足以滿足需求&#xff1f;1.3 MySQL Elas…

PPL困惑度的計算

1. 公式 PPL&#xff08;Perplexity&#xff09;困惑度 是自然語言處理&#xff08;NLP&#xff09;中常用的評估語言模型&#xff08;Language Model&#xff09;性能的指標。PPL 用于衡量語言模型對語言序列的預測能力&#xff0c;數值越小&#xff0c;說明模型的預測能力越…

MegaCLI Raid管理工具

整理在CentOS 7.9和Ubuntu 24.04上&#xff0c;MegaCLI 工具的安裝與常用命令。 1. 參考 下載和安裝MegaCLI工具 MegaCli RAID管理工具 Megacli 批量磁盤巡檢 ubuntu24.04 No such file libncursesw.so.5 dell服務器硬盤的狀態變成外來&#xff08;foreign&#xff09;命…

HTML9:頁面結構分析

頁面結構分析 元素名描述header標題頭部區域的內容&#xff08;用于頁面或頁面中的一塊區域&#xff09;footer標記腳部區域的內容&#xff08;用于整個頁面或頁面的一塊區域&#xff09;sectionWeb頁面的一塊獨立區域article獨立的文章內容aside相關的內容或應用&#xff08;…

分布式處理架構

分布式處理架構是一種將計算任務分散到多臺計算機或服務器上協同完成的系統設計方法。這種架構通過將工作負載分配到多個節點&#xff08;可以是物理機、虛擬機或容器&#xff09;來提高性能、可靠性和可擴展性。下面我將從多個角度詳細解釋這一概念&#xff1a; 分布式架構的…

算法每日一題 | 入門-分支結構-Apples Prologue/蘋果和蟲子

Apples Prologue/蘋果和蟲子 題目描述 小 B 喜歡吃蘋果。她現在有 m m m&#xff08;1 ≤ m ≤100&#xff09;個蘋果&#xff0c;吃完一個蘋果需要花費 t t t&#xff08;0 ≤ t≤ 100&#xff09;分鐘&#xff0c;吃完一個后立刻開始吃下一個。 現在時間過去了 s s s&a…

RT Thread Studio創建軟件和硬件RTC工程

MCU型號&#xff1a;STM32F103RET6 一.配置軟件模擬RTC 1.生成一個帶串口輸出的工程文件&#xff0c;新建RT-Thread項目工程文件。 2.查看電路圖中的串口輸出管腳&#xff0c;根據STMCubeMx軟件可知此串口為USART1&#xff0c;選擇芯片型號為STM32F103RET6&#xff0c;控制臺…

STC32G12K128-旋轉編碼器-軟件去抖

STC32G12K128-旋轉編碼器-軟件去抖 簡介代碼 簡介 EC11旋轉編碼器是一種可以連續旋轉的器件A,B,C為旋轉編碼引腳&#xff0c;帶按鍵的有D,E引腳。引腳功能&#xff1a; A&#xff1a;編碼器A相&#xff1b;B&#xff1a;編碼器B相&#xff1b;C&#xff1a;公共端-一般接到GN…

配置Jupyter Notebook環境及Token認證(Linux服務器)

配置Jupyter Notebook環境及Token認證&#xff08;Linux服務器&#xff09; 背景 在Ubuntu 18.04.6 LTS服務器&#xff08;IP: 39.105.167.2&#xff09;上&#xff0c;基于虛擬環境pytorch_env&#xff0c;通過Mac終端&#xff08;SSH&#xff09;配置Jupyter Notebook環境&…

從零開始學Flink:開啟實時計算的魔法之旅

在凌晨三點的數據監控大屏前&#xff0c;某電商平臺的技術負責人突然發現一個異常波動&#xff1a;支付成功率驟降15%。傳統的數據倉庫此時還在沉睡&#xff0c;而基于Flink搭建的實時風控系統早已捕捉到這個信號&#xff0c;自動觸發預警機制。當運維團隊趕到時&#xff0c;系…

基于k8s的Jenkins CI/CD平臺部署實踐(三):集成ArgoCD實現持續部署

基于k8s的Jenkins CI/CD平臺部署實踐&#xff08;三&#xff09;&#xff1a;集成ArgoCD實現持續部署 文章目錄 基于k8s的Jenkins CI/CD平臺部署實踐&#xff08;三&#xff09;&#xff1a;集成ArgoCD實現持續部署一、Argocd簡介二、安裝Helm三、Helm安裝ArgoCD實戰1. 添加Arg…

[C++類和對象]類和對象的引入

面向過程和面向對象 C語言是面向過程的,關注的是過程,分析出求解問題的步驟,通過函數調用來逐步解決問題 C是基于面向對象的,關注的是對象,將一件事情分成不同的對象,靠對象之間完成交互 類的引入 C語言結構體中只能定義變量,在C中,結構體不僅僅可以定義變量,而且可以定義函…

AWS之存儲服務

目錄 一、傳統存儲術語 二、傳統存儲與云存儲的關系 三、云存儲之AWS 使用場景 文件存儲 數據塊存儲 對象存儲 EBS、EFS、S3對比 EBS塊存儲 S3對象存儲 S3 使用案例 S3 存儲類 EFS文件存儲 一、傳統存儲術語 分類 接口/技術類型 應用場景特點 關系及區別 機械硬…

WPDRRC 模型:構建動態閉環的信息安全防御體系

WPDRRC 模型是一種信息安全整體架構設計模型&#xff0c;由預警&#xff08;Warning&#xff09;、保護&#xff08;Protection&#xff09;、檢測&#xff08;Detection&#xff09;、反應&#xff08;Reaction&#xff09;、恢復&#xff08;Recovery&#xff09;和反擊&…

Redis 數據類型詳解(二):Hash 類型全解析

文章目錄 一、什么是 Redis 的 Hash 類型&#xff1f;二、Hash為什么在有些時候比String好用三、常見命令1.HSET key field value2.HGET key field3.HMSET4.HMGET5.HGETALL6.HKEYS7.HVALS8.HINCRBY9.HSETNX 四、應用場景五、性能優勢六、注意事項總結 提示&#xff1a;以下是本…

Go Modules 的基本使用

在 Go Modules 項目中&#xff0c;首次運行時下載依賴包的正確流程需要根據項目情況區分處理。以下是詳細步驟和最佳實踐&#xff1a; 一、首次初始化項目的標準流程 1.1 創建項目目錄并初始化模塊 mkdir myproject && cd myproject go mod init github…

RISC-V AIA SPEC學習(五)

第六章 Interrupts for Virtual Machines(VS Level) 核心內容 1.VS級別外部中斷支持:?? ??客戶中斷文件(Guest Interrupt File)??:虛擬機的每個vCPU擁有獨立的IMSIC中斷文件,允許直接接收設備MSI。??vstopi CSR??:類似stopei,用于虛擬機內部處理最高優先級中…

【Python-Day 11】列表入門:Python 中最靈活的數據容器 (創建、索引、切片)

Langchain系列文章目錄 01-玩轉LangChain&#xff1a;從模型調用到Prompt模板與輸出解析的完整指南 02-玩轉 LangChain Memory 模塊&#xff1a;四種記憶類型詳解及應用場景全覆蓋 03-全面掌握 LangChain&#xff1a;從核心鏈條構建到動態任務分配的實戰指南 04-玩轉 LangChai…

【AXI總線專題】-AXI-LITE總線解讀

【AXI總線專題】-AXI-LITE總線解讀 1.axi-lite概述2.信號定義Write address channelWrite data channelWrite response channelRead address channelRead data channel 3.測試4.仿真波形5.工程文件 參考手冊 《3-2-03米聯客2022版AXI4總線專題-20211123.pdf》 《IHI0022E_amba_…

在企業級項目中高效使用 Maven-mvnd

1、引言 1.1 什么是 Maven-mvnd? Maven-mvnd 是 Apache Maven 的一個實驗性擴展工具(也稱為 mvnd),基于守護進程(daemon)模型構建,目標是顯著提升 Maven 構建的速度和效率。它由 Red Hat 推出,通過復用 JVM 進程來減少每次構建時的啟動開銷。 1.2 為什么企業在構建過…