中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

如何做網(wǎng)站本地服務(wù)器嗎廣告投放策略

如何做網(wǎng)站本地服務(wù)器嗎,廣告投放策略,網(wǎng)站怎么做內(nèi)鏈,蘇州微網(wǎng)站建設(shè)公司唯有夢想才配讓你不安, 唯有行動(dòng)才能解除你的不安。 --- 盧思浩 --- 從零開始掌握序列化 1 知識(shí)回顧2 序列化與編寫協(xié)議2.1 使用Json進(jìn)行序列化2.2 編寫協(xié)議 3 封裝IOService4 應(yīng)用層 --- 網(wǎng)絡(luò)計(jì)算器5 總結(jié) 1 知識(shí)回顧 上一篇文章我們講解了協(xié)議的本質(zhì)是雙方能夠…

在這里插入圖片描述

唯有夢想才配讓你不安,
唯有行動(dòng)才能解除你的不安。
--- 盧思浩 ---

從零開始掌握序列化

  • 1 知識(shí)回顧
  • 2 序列化與編寫協(xié)議
    • 2.1 使用Json進(jìn)行序列化
    • 2.2 編寫協(xié)議
  • 3 封裝IOService
  • 4 應(yīng)用層 --- 網(wǎng)絡(luò)計(jì)算器
  • 5 總結(jié)

1 知識(shí)回顧

上一篇文章我們講解了協(xié)議的本質(zhì)是雙方能夠看到的結(jié)構(gòu)化數(shù)據(jù)。并通過傳輸層的底層理解了為什么read系列函數(shù)時(shí)全雙工支持同時(shí)讀寫的:TCP傳輸層有兩個(gè)緩沖區(qū),分別接收和發(fā)送。最重要的是我們將TCP通信的代碼進(jìn)行的重構(gòu):

  1. 我們將Socket通信單獨(dú)封裝為一個(gè)類,負(fù)責(zé)Socket套接字的創(chuàng)建,bind綁定服務(wù)器端口號(hào),進(jìn)入監(jiān)聽模式…工作,基類Socket并不進(jìn)行定義,只進(jìn)行聲明!具體實(shí)現(xiàn)由派生類TcpServer和UdpServer來進(jìn)行
  2. TcpServer繼承Socket類的所有方法,然后進(jìn)行具體的函數(shù)定義!
  3. 上層的TcpServer直接底層使用TcpSocket對(duì)象就可以完成Socket系列操作,十分方便!

接下來我們要實(shí)現(xiàn)是這樣的一個(gè)結(jié)構(gòu):
在這里插入圖片描述
通信過程整體分為三層

  1. 傳輸層TcpServer:負(fù)責(zé)從Socket文件中獲取鏈接,傳輸層不需要進(jìn)行IO,獲取到連接就讓會(huì)話層通過連接獲取數(shù)據(jù)!
  2. 會(huì)話層Service:根據(jù)傳輸層給的連接,從Sockfd文件中讀取數(shù)據(jù),解析出報(bào)文結(jié)構(gòu)中的數(shù)據(jù)字符串,然后通過協(xié)議分離出結(jié)構(gòu)化數(shù)據(jù)。該層只負(fù)責(zé)數(shù)據(jù)的解析,數(shù)據(jù)的處理交給應(yīng)用層進(jìn)行!
  3. 應(yīng)用層Process:應(yīng)用層是具有的業(yè)務(wù)邏輯,根據(jù)會(huì)話層解析出的數(shù)據(jù),進(jìn)行數(shù)據(jù)處理!

這樣是一個(gè)非常非常優(yōu)雅的封裝操作!!!

2 序列化與編寫協(xié)議

2.1 使用Json進(jìn)行序列化

協(xié)議是IO的基礎(chǔ),只有協(xié)議確定下來,才可以進(jìn)行通信。
我們這里想要實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)計(jì)算器的應(yīng)用,所以協(xié)議分為了兩個(gè)類:Request和Response。分別作為傳入的數(shù)據(jù)和傳出的數(shù)據(jù):

  1. Request:兩個(gè)數(shù)字和一個(gè)運(yùn)算符
  2. Response:結(jié)果數(shù)字 , 錯(cuò)誤碼 ,退出信息

他們是作為結(jié)構(gòu)化的數(shù)據(jù)進(jìn)行傳輸,那么想要進(jìn)行傳輸就來到了最重要的部分序列化與反序列化!序列化與反序列化可以使用第三方庫也可以自己進(jìn)行編寫。這里我們先使用第三方的Json庫進(jìn)行實(shí)現(xiàn):

Jsoncpp 是一個(gè)用于處理 JSON 數(shù)據(jù)的 C++ 庫。 它提供了將 JSON 數(shù)據(jù)序列化為字符串以及從字符串反序列化為 C++ 數(shù)據(jù)結(jié)構(gòu)的功能。 Jsoncpp 是開源的, 廣泛用于各種需要處理 JSON 數(shù)據(jù)的 C++ 項(xiàng)目中:

  1. 簡單易用: Jsoncpp 提供了直觀的 API, 使得處理 JSON 數(shù)據(jù)變得簡單。
  2. 高性能: Jsoncpp 的性能經(jīng)過優(yōu)化, 能夠高效地處理大量 JSON 數(shù)據(jù)。
  3. 全面支持: 支持 JSON 標(biāo)準(zhǔn)中的所有數(shù)據(jù)類型, 包括對(duì)象、 數(shù)組、 字符串、 數(shù)字、 布爾值和 null。
  4. 錯(cuò)誤處理: 在解析 JSON 數(shù)據(jù)時(shí), Jsoncpp 提供了詳細(xì)的錯(cuò)誤信息和位置, 方便開發(fā)者調(diào)試

在Linux中使用需要進(jìn)行安裝對(duì)應(yīng)的JSON庫:

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

安裝之后就可以進(jìn)行使用了:

使用起來是十分方便的:

  1. Json::Value是最重要的類,這是對(duì)Json數(shù)據(jù)結(jié)構(gòu)進(jìn)程操作和表示的關(guān)鍵類
  2. 建立好類Json::Value之后就可以通過[ ]操作root["x"] = _x;,像這樣就可以進(jìn)行賦值
  3. 將Json數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為字符串依靠 Json::FastWriter 或 Json::StreamWriter都可以轉(zhuǎn)換成字符串
Json::StyledWriter writer;
std::string s = writer.write(root)
  1. 通過Json::Reader可以快速將字符串反序列化得到Json結(jié)構(gòu)!
bool parsingSuccessful = reader.parse(json_string,root);
// 訪問 JSON 數(shù)據(jù) 
std::string name = root["name"].asString();
int age = root["age"].asInt(); std::string city =
root["city"].asString();

通過這樣就就可以簡潔的完成序列化與反序列化的工作!

2.2 編寫協(xié)議

根據(jù)我們的需求在加入Json操作我們就可以把協(xié)議寫出來,代碼雖然很長但是很好理解:

  1. Request類中需要根據(jù) int x , int y , char oper進(jìn)行序列化生成字符串,也要能夠通過字符串反序列化得到三個(gè)變量
  2. Response類中需要根據(jù) int res , int code , std::string desc進(jìn)行序列化生成字符串,也要能夠通過字符串反序列化得到三個(gè)變量
#pragma once
#include <jsoncpp/json/json.h>
#include <string>
// 協(xié)議就是雙方都認(rèn)識(shí)的結(jié)構(gòu)化數(shù)據(jù)
// "len"\r\n"{json}"\r\n
const std::string sep = "\r\n";struct Request
{
public:Request() {}Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper){}~Request(){}bool Serialize(std::string *out){// 使用現(xiàn)成的 Json 庫Json::Value root;root["x"] = _x;root["y"] = _y;root["oper"] = _oper;Json::FastWriter writer;std::string s = writer.write(root);*out = s;return true;}bool Deserialize(std::string &in){Json::Value root;    // 創(chuàng)建json對(duì)象Json::Reader reader; // 讀取bool res = reader.parse(in, root);if (res == false)return false;_x = root["x"].asInt();_y = root["y"].asInt();_oper = root["oper"].asInt();return true;}int X() { return _x; }int Y() { return _y; }char Oper() { return _oper; }private:int _x;int _y;char _oper;
};struct Response
{Response() {}Response(int res, int code, std::string desc) : _res(res), _code(code), _desc(desc){}~Response(){}bool Serialize(std::string *out){// 使用現(xiàn)成的 Json 庫Json::Value root;root["res"] = _res;root["code"] = _code;root["desc"] = _desc;Json::FastWriter writer;std::string s = writer.write(root);*out = s;return true;}bool Deserialize(std::string &in){Json::Value root;    // 創(chuàng)建json對(duì)象Json::Reader reader; // 讀取bool res = reader.parse(in, root);if (res == false)return false;_res = root["res"].asInt();_code = root["code"].asInt();_desc = root["desc"].asInt();return true;}int _res;int _code; // 退出碼 0:success 1:div zero 2:非法操作std::string _desc;
};

看一下效果:
在這里插入圖片描述

完成了基礎(chǔ)的序列化和反序列化之后,我們就可以做到從sockfd流中讀取數(shù)據(jù)了嗎??不可以!因?yàn)椴恢繨son字符串的長度,就不知道應(yīng)該讀取多少字節(jié)!這樣可就做不到正確的從數(shù)據(jù)中獲取json字符串!

所以我們還有做一步特殊處理:

  • 需要對(duì)生成的Json字符串加入報(bào)頭len記錄json字符串的長度,中間以sep分隔符分割!
  • 需要對(duì)獲得到的數(shù)據(jù)進(jìn)行解析,去除報(bào)頭得到一個(gè)Json字符串!
// "len"\r\n"{json}"\r\n
const std::string sep = "\r\n";
// 加入報(bào)頭
std::string Encode(const std::string &jsonstr)
{int len = jsonstr.size();std::string lenstr = std::to_string(len);return lenstr + sep + jsonstr + sep;
}std::string Decode(std::string &packagestream)
{auto pos = packagestream.find(sep);if (pos == std::string::npos)return std::string();// 獲取到lenstd::string lenstr = packagestream.substr(0, pos);int len = std::stoi(lenstr);//算上報(bào)頭的完整長度!int total = lenstr.size() + len + 2 * sep.size();if (total > packagestream.size())return std::string();// 到這里說明可以讀取完整數(shù)據(jù)std::string jsonstr = packagestream.substr(pos + sep.size(), len);packagestream.erase(total);return jsonstr;
}

經(jīng)過這樣的操作,可以保證:

  • 上層想要發(fā)送數(shù)據(jù)時(shí),可以將數(shù)據(jù)包裝為json字符串,并加入報(bào)頭形成完整報(bào)文!
  • 上層獲取數(shù)據(jù)進(jìn)行反序列化時(shí)可以獲取到完整的json字符串!并成功解析為數(shù)據(jù)

3 封裝IOService

將來我們的線程會(huì)執(zhí)行將會(huì)執(zhí)行這個(gè)回調(diào)函數(shù)方法,現(xiàn)在我們不再需要TcpServer來進(jìn)行IO操作,TcpServer只負(fù)責(zé)進(jìn)行獲取鏈接,獲取到連接后通過ThreadData結(jié)構(gòu)體將數(shù)據(jù)傳到線程中的回調(diào)函數(shù)中:

	class ThreadData{public:SockSPtr _sockfd;InetAddr _addr;TcpServer *_this;public:ThreadData(SockSPtr sockfd, InetAddr addr, TcpServer *p) : _sockfd(sockfd),_this(p),_addr(addr){}};

在回調(diào)函數(shù)Execute中:

// 注意設(shè)置為靜態(tài)函數(shù) , 不然參數(shù)默認(rèn)會(huì)有TcpServer* this!!!static void *Execute(void *args){pthread_detach(pthread_self()); // 線程分離!!!// 執(zhí)行Service函數(shù)TcpServer::ThreadData *td = static_cast<TcpServer::ThreadData *>(args);td->_this->_service(td->_sockfd, td->_addr);td->_sockfd->Close();delete td;return nullptr;}

就可以解析出來套接字文件描述符和客戶端信息了!解析出信息之后就去執(zhí)行會(huì)話層的回調(diào)函數(shù)進(jìn)行IO操作:

  1. Service內(nèi)部只有一個(gè)成員變量,就是應(yīng)用層的回調(diào)函數(shù),Service解析出來數(shù)據(jù)之后就可以傳入到應(yīng)用層中進(jìn)行使用
  2. IO中主要需要進(jìn)行從sockfd文件中獲取數(shù)據(jù),然后通過協(xié)議進(jìn)行解析,獲取到真正的數(shù)據(jù)。再調(diào)用回調(diào)函數(shù)對(duì)數(shù)據(jù)進(jìn)行操作!得到結(jié)果之后就可以進(jìn)行序列化,加入報(bào)頭,再發(fā)送給客戶端!
  3. 應(yīng)用層的操作邏輯,Service并不關(guān)心,只要回調(diào)函數(shù)可以傳回需要的結(jié)構(gòu)體就可以!
class Service
{
public:Service(process_t process) : _process(process){}void IOExecute(SockSPtr sock, InetAddr &addr){LOG(INFO, "service start!!!\n");std::string message;while (true){// 1. 進(jìn)行讀取ssize_t n = sock->Recv(&message);if (n < 0){LOG(ERROR, "read error: %s\n", addr.AddrStr().c_str());break;}// 此時(shí)獲取到客戶端發(fā)送的數(shù)據(jù)// 但是不能保證是否是完整的報(bào)文// 2.報(bào)文解析std::string str = Decode(message); // 通過去報(bào)頭獲取報(bào)文if (str.empty())continue; // 說明沒有完整的報(bào)文!// 到這里說明有完整的報(bào)文!!!auto req = Factory::BuildRequestDefault();// 3.反序列化初始化Requestreq->Deserialize(str);auto res = Factory::BuildResponseDefault();// 4.業(yè)務(wù)處理res = _process(req);// 5.進(jìn)行序列化處理std::string ret;res->Serialize(&ret);// 6.加入報(bào)頭Encode(ret);// 7.將獲取的數(shù)據(jù)發(fā)送回去sock->Send(ret);}}~Service(){}private:process_t _process;
};

4 應(yīng)用層 — 網(wǎng)絡(luò)計(jì)算器

應(yīng)用層根據(jù)具體需要可以隨時(shí)改變,我這里以網(wǎng)絡(luò)計(jì)算器為例子進(jìn)行書寫:

#include "Protocol.hpp"
class NetCal
{
public:NetCal() {}std::shared_ptr<Response> Calculator(std::shared_ptr<Request> req){std::shared_ptr<Response> res = Factory::BuildResponseDefault();switch (req->Oper()){case '+':res->_res = req->X() + req->Y();res->_code = 0;res->_desc = "success";break;case '-':res->_res = req->X() - req->Y();res->_code = 0;res->_desc = "success";break;case '*':res->_res = req->X() * req->Y();res->_code = 0;res->_desc = "success";break;case '/':{if (req->Y() == 0){res->_code = 1;res->_desc = "div zero";}res->_res = req->X() / req->Y();res->_code = 0;res->_desc = "success";}break;case '%':{if (req->Y() == 0){res->_code = 1;res->_desc = "mod zero";}res->_res = req->X() % req->Y();res->_code = 0;res->_desc = "success";}break;default:res->_code = 2;res->_desc = "illegal operations";break;}return res;}~NetCal() {}
};

邏輯很簡單不在多加贅述!

5 總結(jié)

現(xiàn)在我們的程序分為了三層結(jié)構(gòu):
在這里插入圖片描述
我們做到了最大程度的解耦!

  • 傳輸層只負(fù)責(zé)獲取鏈接,我們應(yīng)用層要進(jìn)行什么工作,只要是進(jìn)行網(wǎng)絡(luò)通信傳輸層的工作就是唯一的!
  • 會(huì)話層進(jìn)行IO操作!只要傳輸層提供了鏈接,會(huì)話層就可以獲取數(shù)據(jù),然后根據(jù)具體的協(xié)議進(jìn)行數(shù)據(jù)的解析工作。協(xié)議根據(jù)實(shí)際情況改變,但是會(huì)話層的工作邏輯是不變的!
  • 應(yīng)用層只管進(jìn)行數(shù)據(jù)處理即可,什么但不不需要考慮!完成工作后返回給會(huì)話層數(shù)據(jù)即可!

這樣的結(jié)構(gòu)邏輯十分清晰,并且解耦的非常優(yōu)雅,值得反復(fù)品味!!!

http://www.risenshineclean.com/news/39620.html

相關(guān)文章:

  • 江蘇省建設(shè)人才網(wǎng)站軟文文案案例
  • 蘭州新站seo如何找推廣平臺(tái)
  • 假網(wǎng)站怎么做呢百度信息流投放技巧
  • 怎么提高網(wǎng)站曝光武漢seo優(yōu)化服務(wù)
  • 高能建站系統(tǒng)怎么收費(fèi)查詢網(wǎng)站流量的網(wǎng)址
  • 網(wǎng)站備案沒公司網(wǎng)絡(luò)口碑營銷的成功案例
  • 主流跨境電商平臺(tái)有哪些?山東服務(wù)好的seo
  • 做酒店網(wǎng)站的公司百度一下子就知道了
  • 個(gè)人網(wǎng)站怎么做視頻人工智能培訓(xùn)心得
  • 北京網(wǎng)頁制作網(wǎng)站搜索引擎網(wǎng)站優(yōu)化推廣
  • 專用主機(jī)網(wǎng)站建設(shè)企業(yè)郵箱域名
  • 鹽城網(wǎng)站建設(shè)流程百度在線使用網(wǎng)頁版
  • WordPress 升級(jí) php蘇州百度快速排名優(yōu)化
  • 頭條號(hào)可以做網(wǎng)站鏈接嗎最近的新聞大事10條
  • 中華人民共和國城鄉(xiāng)建設(shè)部網(wǎng)站百度打廣告收費(fèi)表
  • 網(wǎng)站的欄目關(guān)鍵詞常用的網(wǎng)絡(luò)推廣方法
  • 有哪些好用的設(shè)計(jì)網(wǎng)站有哪些內(nèi)容培訓(xùn)心得體會(huì)怎么寫
  • 好看的中文網(wǎng)站設(shè)計(jì)百度一下首頁登錄入口
  • 各種類型網(wǎng)站建設(shè)獨(dú)立aso關(guān)鍵詞優(yōu)化計(jì)劃
  • 鄭州市域名服務(wù)公司網(wǎng)絡(luò)公司seo教程
  • 網(wǎng)站后端技術(shù)有哪些運(yùn)營商大數(shù)據(jù)精準(zhǔn)營銷獲客
  • 做網(wǎng)站找誰百度服務(wù)中心投訴
  • 網(wǎng)站的思維導(dǎo)圖怎么做線上怎么做推廣和宣傳
  • 做app推廣上哪些網(wǎng)站嗎2022年今天新聞聯(lián)播
  • 服務(wù)周到的做網(wǎng)站自媒體軟文發(fā)布平臺(tái)
  • 織夢手機(jī)網(wǎng)站怎么安裝教程視頻在線網(wǎng)絡(luò)培訓(xùn)平臺(tái)
  • 河北網(wǎng)站制作網(wǎng)絡(luò)營銷與管理
  • 怎么做網(wǎng)站免費(fèi)常用的網(wǎng)絡(luò)營銷方法有哪些
  • 誰知道蘇州溪城水處理網(wǎng)站誰做的今日短新聞20條
  • 020網(wǎng)站建設(shè)專業(yè)網(wǎng)站建設(shè)公司