1.應用層

1.1再談“協議”
約定方案
? 定義結構體來表示我們需要交互的信息;
? 發送數據時將這個結構體按照一個規則轉換成字符串, 接收到數據的時候再按
照相同的規則把字符串轉化回結構體;
? 這個過程叫做 "序列化" 和 "反序列化"
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 進程組

5.1.2 組長進程
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 會話
C
#include <unistd.h>
/*
*功能:創建會話
*返回值:創建成功返回 SID, 失敗返回-1
*/
pid_t setsid(void);

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

5.4 作業控制
5.4.2 作業的掛起與切回
5.4.3 查看后臺執行或掛起的作業
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?作業控制相關的信號
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
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" : "男"
}
#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" : "男"
}
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. 反序列化
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: 北京