文章目錄
- json庫
- 粗略認識
- 詳細認識
- writer 類
- reader類
- jsoncpp序列化實現
- jsoncpp反序列化實現
- bundle文件壓縮庫
- 簡單認識
- bundle庫實現文件壓縮
- bundle庫實現文件解壓縮
- httplib庫
- Request類
- Response類
- Server類
- Client類
json庫
粗略認識
json是一種數據交換格式,采用完全獨立于編程語言的文本格式來存儲和表示數據

姓名是char類型、年齡是 int類型、 成績是 float類型
json將多種數據類型對象 組織成為一個字符串
json數據類型:對象、數組、字符串、數字
對象:使用 {} 括起來的表示一個對象
如:小明 和小黑 兩個 學生信息對象
數組:使用 [] 括起來的表示一個數組
如:小明和小黑的成績都有三個數,用[] 括起來 表示一個數組
字符串:使用" "括起來的表示一個字符串
如:小明和小黑的名字 使用雙引號,表示字符串
數字:包括整形和浮點型 直接使用
如:小明和小黑的年齡 可以直接 填入 即可
詳細認識
jsoncpp庫 用于實現 json格式 的序列化和反序列化,完成將多個數據對象組織成為 json格式字符串
以及將json格式字符串 解析得到多個數據對象的功能
主要借助三個類以及對應的成員函數完成:

該類中重載了 [] 和 = 兩個運算符
好處是 進行數據存儲時,json::value類會保存所有的數據對象
也可以用 asString 尋找對應數據中屬于string的部分
用 asInt 尋找對應數據中屬于int的部分
writer 類
將json::value 對象中所保存的多個數據對象的數據 進行序列化

json_api writer json_api fastwriter 、 json_api styledwriter 作為低版本
使用低版本,可能會報警告

json_api streamwriter json_api streanwriterbuilder 作為高版本
使用高版本,則不會有警告
無論低版本還是高版本 都有 write 這個成員函數
傳遞一個 json::value的數據對象,將這個對象中的所有的數據 按照 json格式 進行序列化
若為低版本,則直接返回一個 json數據串
若為高版本,則 將json 數據串 放入 流中
reader類

實現 json的反序列化
即 將json格式的字符串 反序列化 解析得到多個數據對象,放入 json::value 對象中

反序列化的低版本 為 json_api reader
使用其中的 parse接口, 第一個參數 decument 作用為 json格式的字符串 傳入
第二個參數root 作用為 將反序列化得到的對象存放到 root中

反序列化的高版本 共有兩種 charreader 和 charreaderbuilder
先通過 charreaderbuilder 類中的 newcharreader接口 實例化一個 charreader 對象
再去通過 調用charreader 類中的 parse 接口
第一個參數為 字符串的起始地址 第二個參數為字符串的結束地址
第三個參數為 json::value對象的指針
將字符串內容進行反序列化 放入 root中
若解析出錯,則會把錯誤信息 放入 第四個參數 errs中
jsoncpp序列化實現

假設有以上信息
1.需要先將數據保存到 json::value 對象中

2.想要使用 json::StreamWriter 進行序列化 ,就需要先借助 json::StreamWriterBuilder 實例化一個 StreamWriter對象
然后再使用 StreamWriter類中的 write接口 ,將數據串 放入流中

將上述信息放入主函數main中

在實例化一個 json::value類型的root對象,將上面的的數據保存到root中
因為 json::value 重載了運算符,所以基礎數據是可以直接通過賦值來完成的

實例化一個 StreamWriterBuilder類型的對象 swb
再通過類中的newStreamWriter接口 實例化一個StreamWriter對象被命名為 sw

定義一個 stringstream 流 ss
在借助StreamWriter類中的 write接口,將root中的數據串 傳入 流中
最后打印流中的數據


輸入 g++ json_example.cpp -o json_example -ljsoncpp
再次執行程序 , 將數據串 顯示到流中
jsoncpp反序列化實現
string str= “{“姓名”:“小黑”,“年齡”:19,“成績”:[58.5,66,35.5]}”;
{外的雙引號 與 {內的雙引號 有歧義 ,就需要用 \ 進行轉義 ,表示用的是 原始的雙引號
string str=R"({“姓名”:“小黑”,“年齡”:19,“成績”:[58.5,66,35.5]})“;
若想簡單寫,則可以使用C++11中的特殊用法 R”( )" 表示括號內部都是原始字符串,所有的字符都已經去除了特殊含義
jsoncpp中進行反序列化 ,是將字符串中的數據解析放到了 Json::Value 中
1.定義一個Json::Value對象 root

2. 想要使用 CharReader 進行反序列化 ,則需要先通過 CharReaderBuilder 實例化一個對象 CharReader
在調用 CharReader 的 parse接口

創建一個str字符串,并且內部都是原始字符串


創建一個 json::value 類型的root對象
實例化一個 json::CharReader類型的對象 crb
再通過類中的 newCharReader接口 實例化一個CharReader 對象被命名為 cr

若ret為false,則說明反序列化失敗
若ret為true, 則說明反序列化成功
root[“姓名”].asString() 表示 獲取到 姓名對應數據中的string數據
所以使用 asString 表示 獲取對應的string數據
root[“年齡”].asInt() 表示 獲取到 年齡對應數據中的int數據
所以使用 asInt 表示 獲取對應的int數據


反序列化后,數據全部放入root中,最終 將root對象中的數據全部打印出來
bundle文件壓縮庫
簡單認識
bundleBundle 是一個嵌入式壓縮庫,使用時只需要加入兩個文件 bundle.h 和 bundle.cpp 即可
bundle庫實現文件壓縮
由于在之前已經安裝過了 bundle庫,所以直接使用 bundle-master

將 bundle-master 中的 bundle.cpp 和 bundle.h 拷貝出來 當到當前目錄中

從運行參數中獲取到文件壓縮的文件名和壓縮包名稱
打開原文件,讀取對應的數據,再對其進行壓縮
共有三個參數,文件壓縮 文件名和壓縮包名稱
如果agv小于3,則表示參數個數不夠,則直接返回-1

iffilename表示文件名稱
offilename表示壓縮包的名稱

使用ifstream文件流 創建變量ifs
open打開原始文件,打開的是輸入文件
輸入 ios::binary i以二進制形式打開文件
iseekg i 作用為跳轉到讀寫位置到末尾

獲取末尾偏移量 即文件長度

跳轉到文件起始位置

創建一個字符串 body
調整body大小為文件大小
讀取文件所有數據到 body中

選擇 LZIP 壓縮格式,body作為文件內容,使用 pack 進行壓縮,返回值就是壓縮之后的數據

以輸出文件流 ofstream 創建變量 ofs
以二進制的方式打開壓縮包 文件
將壓縮后的數據寫入 壓縮包文件中



執行compress可執行程序 即可運行出來

bundle.cpp文件大小為5.4M
通過compress 將其 進行壓縮成 bundle.cpp.lz
再次查看發現bundle.cpp.lz大小為668K
bundle庫實現文件解壓縮
將文件壓縮后的 bundle.cpp.lz 進行解壓 , 再將解壓的文件與 bundle.cpp進行對比

共有三個參數,文件壓縮 壓縮包名稱和文件名稱
如果agv小于3,則表示參數個數不夠,則直接返回-1

以 istream文件流 創建變量 ifs
將filename文件 以二進制形式打開
使用 seekg 使 ifs 處于文件末尾
再通過 tellg 獲取文件大小
最終通過 beg 跳轉到 ifs文件的起始位置

創建一個字符串 body
調整body大小為文件大小
讀取ifs文件所有數據到 body中

通過 bundle 庫中的 unpack 進行解壓縮

以 輸出文件流ofstram 創建變量 ofs
以二進制形式,將ofilename文件打開
將解壓縮后的數據 全部放入 ofs文件 中


httplib庫
httplib庫 是一個c++11單文件頭的跨平臺 HTTP/HTTPS庫
只需包含 httplib.h 在代碼中即可
實際用于搭建一個簡單的http服務器或者客戶端的庫,這種第三方庫免去搭建服務器或客戶端的時間,提高開發效率
Request類

HTTP
首行: 請求方法 URL 協議版本
頭部:key 與value 形成的KV模型
空行:\r\n
正文:提交給服務器的數據
請求方法中包含 GET獲取資源 以及 POST提交表單數據
Request結構體的作用:
1.客戶端保存的所有http請求相關信息,最終組織http請求發送給服務器
2.服務器收到http請求之后進行解析,將解析的數據保存在request結構體中,等待后續處理


MultipartFormDataMap 內部包含四個字段
name為字段名稱
content為文件內容
filename為文件名稱
coneent_type 為正文類型

has_header 查詢頭部字段
get_heaer_value 獲取頭部字段的值
set_header 設置頭部字段的值
has_file 是否包含某個文件
get_file_value 獲取文件信息
Response類

HTTP響應格式
首行:協議版本 響應狀態碼 狀態碼描述
頭部:響應的關鍵性描述字段 key: value\r\n key:value\r\n
空行: \r\n
正文:響應給客戶端的數據
Response結構體功能
用戶將響應數據放到結構體中,httplib會將其中的數據按照http響應格式 組織成為http
Server類
Server功能
用于搭建http服務器

listen作為搭建服務器并啟動http服務器

handler是一個函數指針類型的業務處理函數,定義了一個http請求處理回調函數格式
第一個參數 request 為 保存請求數據,讓用戶能夠根據請求數據進行業務處理
第二個參數 response 為 用戶在業務處理中,填充數據,最終要響應給客戶端
http搭建的服務器收到請求后,進行解析,得到一個Request結構體,其中包含請求數據
根據請求數據 就可以將請求處理,處理函數定義的格式為Handler格式

Handlers是 請求與處理函數映射表
為一個請求路由數組,數組中包含兩個信息
regex 為 正則表達式 用于匹配 http請求資源路徑
Handler 為 請求處理函數指針
可以將 Handlers 看作一張表 映射了客戶端請求的資源路徑和一個處理函數(用戶自己定義的函數)
當服務器收到請求解析得到 Request 就會根據 資源路徑以及請求方法到這張表中查看有沒有對應的處理函數
如果有則調用這個函數進行請求處理
如果沒有則響應404

new_task_queue 作為一個線程池 用于處理請求
httplib 會收到一個新建 連接,則將新的客戶端連接拋入 線程池中
線程池中線程的工作:
1.接收請求,解析請求,得到request結構體 即請求數據
2.在Handlers映射表中,根據請求信息 查找處理函數,如果有則調用函數處理,如果沒有則響應404
3.當處理函數調用完畢后,根據函數返回的response結構體中的數據 組織 http響應 發送給客戶端
Client類

Client類 用于搭建 http的客戶端
GET 向服務器發送GET請求
傳入的是 請求的資源路徑和 頭部字段
第一個POST 發送post請求
path為資源路徑、body作為正文數據、length作為正文長度、content_type 作為 正文類型
第二個POST POST請求提交多區域數據 常用于多文件上傳
path為資源路徑
MultipartFormDataItems 是一個數組,而items 為上傳的文件信息