【C++項目】從零實現RPC框架「三」:項?抽象層實現

?? 個人主頁:Zfox_
?? 系列專欄:C++從入門到精通

目錄

  • 一:?? 常?的零碎功能接?類實現
    • ?? 簡單?志宏實現
    • ?? Json 序列化/反序列化
    • ?? UUID ?成
  • 二:?? 項?消息類型字段信息定義
    • ?? 請求字段宏定義
    • ?? 消息類型定義
    • ?? 響應碼類型定義
    • ?? RPC 請求類型定義
    • ?? 主題操作類型定義
    • ?? 服務操作類型定義
  • 三:?? 通信抽象實現
  • 四:?? 消息抽象實現
  • 五:?? 通信 - Muduo 封裝實現
  • 六:?? Dispatcher 實現
  • 七:?? 共勉

一:?? 常?的零碎功能接?類實現

detail.hpp

?? 簡單?志宏實現

????? 意義:快速定位程序運?邏輯出錯的位置。

項?在運?中可能會出現各種問題,出問題不可怕,關鍵的是要能找到問題,并解決問題。

解決問題的?式:

  • gdb 調試:逐步調試過于繁瑣,緩慢。主要?于程序崩潰后的定位。
  • 系統運??志分析:在任何程序運?有可能邏輯錯誤的位置進?輸出提?,快速定位邏輯問題的位置。
#include <iostream>
#include <cstdio>
#include <string>
#include <fstream>
#include <sstream>
#include <memory>
#include <filesystem> // c++17
#include <random>
#include <time.h>
#include "Mutex.hpp"namespace rpc
{using namespace LockModule;// 獲取一下當前系統的時間std::string CurrentTime(){time_t time_stamp = ::time(nullptr);struct tm curr;localtime_r(&time_stamp, &curr); // 時間戳,獲取可讀性較強的時間信息Schar buffer[1024];// bugsnprintf(buffer, sizeof(buffer), "%4d-%02d-%02d %02d:%02d:%02d",curr.tm_year + 1900,curr.tm_mon + 1,curr.tm_mday,curr.tm_hour,curr.tm_min,curr.tm_sec);return buffer;}// 構成:1. 構建日志字符串 2. 刷新落盤(screen, file)// 1. 日志文件的默認路徑和文件名const std::string defaultlogpath = "./log/";const std::string defaultlogname = "log.txt";// 2. 日志等級enum class LogLevel{DEBUG = 1,INFO,WARNING,ERROR,FATAL};std::string Level2String(LogLevel level){switch (level){case LogLevel::DEBUG:return "DEBUG";case LogLevel::INFO:return "INFO";case LogLevel::WARNING:return "WARNING";case LogLevel::ERROR:return "ERROR";case LogLevel::FATAL:return "FATAL";default:return "None";}}// 3. 刷新策略class LogStrategy{public:virtual ~LogStrategy() = default;virtual void SyncLog(const std::string &message) = 0;};// 3.1 控制臺策略class ConsoleLogStrategy : public LogStrategy{public:ConsoleLogStrategy(){}~ConsoleLogStrategy(){}void SyncLog(const std::string &message){LockGuard lockguard(_lock);std::cout << message << std::endl;}private:Mutex _lock;};// 3.2 文件級(磁盤)策略class FileLogStrategy : public LogStrategy{public:FileLogStrategy(const std::string &logpath = defaultlogpath, const std::string &logname = defaultlogname): _logpath(logpath), _logname(logname){// 確認_logpath是存在的LockGuard lockguard(_lock);if (std::filesystem::exists(_logpath)){return;}try{std::filesystem::create_directories(_logpath);}catch (const std::filesystem::filesystem_error &e){std::cerr << e.what() << '\n';}}~FileLogStrategy(){}void SyncLog(const std::string &message){LockGuard lockguard(_lock);std::string log = _logpath + _logname; // ./log/log.txtstd::ofstream out(log, std::ios::app); // 日志寫入,一定是追加if (!out.is_open()){return;}out << message << '\n';out.close();}private:std::string _logpath;std::string _logname;Mutex _lock;};// 日志類:構建日志字符串,根據策略,進行刷新class Logger{public:Logger(){// 默認采用ConsoleLogStrategy策略_strategy = std::make_shared<ConsoleLogStrategy>();}void EnableConsoleLog(){_strategy = std::make_shared<ConsoleLogStrategy>();}void EnableFileLog(){_strategy = std::make_shared<FileLogStrategy>();}~Logger(){}// 一條完整的信息:[2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [16] + 日志的可變部分(<< "hello world" << 3.14 << a << b;)class LogMessage{public:LogMessage(LogLevel level, const std::string &filename, int line, Logger &logger): _currtime(CurrentTime()), _level(level), _pid(::getpid()), _filename(filename), _line(line), _logger(logger){std::stringstream ssbuffer;ssbuffer << "[" << _currtime << "] "<< "[" << Level2String(_level) << "] "<< "[" << _pid << "] "<< "[" << _filename << "] "<< "[" << _line << "] - ";_loginfo = ssbuffer.str();}template <typename T>LogMessage &operator<<(const T &info){std::stringstream ss;ss << info;_loginfo += ss.str();return *this;}~LogMessage(){if (_logger._strategy){_logger._strategy->SyncLog(_loginfo);}}private:std::string _currtime; // 當前日志的時間LogLevel _level;       // 日志等級pid_t _pid;            // 進程pidstd::string _filename; // 源文件名稱??int _line;             // 日志所在的行號Logger &_logger;       // 負責根據不同的策略進行刷新std::string _loginfo;  // 一條完整的日志記錄};// 就是要拷貝LogMessage operator()(LogLevel level, const std::string &filename, int line){return LogMessage(level, filename, line, *this); // 優化成一次構造一次析構了 連續的構造 + 拷貝構造}private:std::shared_ptr<LogStrategy> _strategy; // 日志刷新的策略方案};Logger logger;#define LOG(Level) logger(Level, __FILE__, __LINE__)
#define ENABLE_CONSOLE_LOG() logger.EnableConsoleLog()
#define ENABLE_FILE_LOG() logger.EnableFileLog()
}

Mutex.hpp 是對Linux下pthread庫的封裝

#pragma once
#include <iostream>
#include <pthread.h>namespace LockModule
{class Mutex{public:Mutex(const Mutex&) = delete;const Mutex& operator = (const Mutex&) = delete;Mutex(){int n = ::pthread_mutex_init(&_lock, nullptr);(void)n;}~Mutex(){int n = ::pthread_mutex_destroy(&_lock);(void)n;}void Lock(){int n = ::pthread_mutex_lock(&_lock);(void)n;}pthread_mutex_t *LockPtr(){return &_lock;}void Unlock(){int n = ::pthread_mutex_unlock(&_lock);(void)n;}private:pthread_mutex_t _lock;};class LockGuard{public:LockGuard(Mutex &mtx):_mtx(mtx){_mtx.Lock();}~LockGuard(){_mtx.Unlock();}private:Mutex &_mtx;};
}

?? Json 序列化/反序列化

#include <iostream>
#include <sstream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>namespace rpc
{class JSON{public:// 實現字符串的序列化static bool Serialize(const Json::Value &val, std::string &body){std::stringstream ss;// 先實例化一個工廠類對象static Json::StreamWriterBuilder swb;// 再使用工廠類對象來生產派生類std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());int ret = sw->write(val, &ss);if (ret != 0){LOG(LogLevel::ERROR) << "Json Serialize failed!";return false;}body = ss.str();return true;}// 實現json字符串的反序列化static bool UnSerialize(const std::string &body, Json::Value &val){// 實例化工廠類對象static Json::CharReaderBuilder crb;std::unique_ptr<Json::CharReader> cr(crb.newCharReader());std::string errs;bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);if (ret == false){LOG(LogLevel::ERROR) << "Json UnSerialize failed! " << errs;return false;}return true;}};
}

?? UUID ?成

UUID (UniversallyUniqueIdentifier),也叫通?唯?識別碼,通常由32位16進制數字字符組成。 UUID的標準型式包含32個16進制數字字符,以連字號分為五段,形式為8-4-4-4-12的32個字符,

如:550e8400-e29b-41d4-a716-446655440000。

在這?,uuid?成,我們采??成8個隨機數字,加上8字節序號,共16字節數組?成32位16進制字符的組合形式來確保全局唯?的同時能夠根據序號來分辨數據(隨機數?眼分辨起來真是太難了…)

#include <iostream>
#include <chrono>

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

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

相關文章

Hadoop集群常用指令詳解

在大數據處理領域&#xff0c;Hadoop作為分布式計算和存儲的開源框架&#xff0c;已經成為不可或缺的工具。掌握Hadoop集群的常用指令對于集群的日常管理和操作至關重要。本文將詳細介紹Hadoop集群的常用指令&#xff0c;幫助讀者更好地理解和使用Hadoop。 一、Hadoop集群的啟…

幾種常見的.NET單元測試模擬框架介紹

目錄 1. Moq 2. NSubstitute 3. AutoFixture 4. FakeItEasy 總結對比 單元測試模擬框架是一種在軟件開發中用于輔助單元測試的工具。 它的主要作用是創建模擬對象來替代真實對象進行測試。在單元測試中&#xff0c;被測試的代碼可能依賴于其他組件或服務&#xff0c;如數…

藍橋杯備賽之枚舉

用循環等方式依次去枚舉所有的數字組合&#xff0c;一一驗證是否符合題目的要求 題目鏈接 0好數 - 藍橋云課 題目解析 好數的概念: 數的奇數位位奇數,偶數位為偶數,就是一個好數 求輸入n里面有多少個好數 題目原理 1> 遍歷每個數 2> 每次遍歷判斷是不是好數 把這…

9、tlm 事務交互通信

1、TLM&#xff08;Transaction-Level Modeling&#xff09; 是 SystemC 的高級建模方法&#xff0c;用于描述系統的通信行為&#xff0c;特別是在硬件設計和驗證中。TLM 是 SystemC 的一部分&#xff0c;用于提高仿真的效率和抽象性。以下是 TLM 的核心知識以及關鍵概念。 2、…

小白入門機器學習概述

文章目錄 一、引言二、機器學習的基礎概念1. 機器學習的定義2. 機器學習的類型&#xff08;1&#xff09;監督學習&#xff08;Supervised Learning&#xff09;&#xff08;2&#xff09;無監督學習&#xff08;Unsupervised Learning&#xff09;&#xff08;3&#xff09;半…

smartdns 在企業場景中的應用心得

smartdns 是一款優秀的本地dns服務器&#xff0c;默認開啟的配置在小型環境下足夠使用(50臺終端)&#xff0c;在面對中大型網絡環境時&#xff08;100臺終端&#xff0c;且有多層網絡結構&#xff09;&#xff0c;需要增加更多的配置來確保穩定運行。 一、刪除注釋&#xff0c;…

【12】Ajax的原理和解析

一、前言 二、什么是Ajax 三、Ajax的基本原理 3.1 發送請求 3.2 解析內容 3.3 渲染網頁 3.4 總結 四、Ajax 分析 五、過濾請求-篩選所有Ajax請求 一、前言 當我們在用 requests 抓取頁面的時候&#xff0c;得到的結果可能會和在瀏覽器中看到的不一樣&a…

【 <二> 丹方改良:Spring 時代的 JavaWeb】之 Spring Boot 中的安全性:使用 Spring Security 實現認證與授權

<前文回顧> 點擊此處查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、開篇整…

百元不入耳藍牙耳機哪個品牌好用?2025百元不入耳耳機品牌推薦

在選擇藍牙耳機時&#xff0c;許多用戶開始關注不入耳式設計&#xff0c;不僅能避免耳道不適&#xff0c;還能保持對環境音的感知&#xff0c;提升運動、通勤或日常使用的安全性。而在百元價位中&#xff0c;不入耳式耳機的品牌眾多&#xff0c;產品質量參差不齊&#xff0c;如…

如何加強 SSH 安全:內網和專用網絡環境下的防護策略

文章目錄 如何加強 SSH 安全&#xff1a;內網和專用網絡環境下的防護策略限制訪問來源通過防火墻或安全組限制網絡策略&#xff08;Network Policy&#xff09; 禁用密碼登錄&#xff0c;使用密鑰認證啟用 Fail2ban 或 SSH 防爆破限制 SSH 用戶更改 SSH 端口使用跳板機&#xf…

ngx_monotonic_time

Ubuntu 下 nginx-1.24.0 源碼分析 - ngx_monotonic_time函數-CSDN博客 定義在 src\core\ngx_times.c static ngx_msec_t ngx_monotonic_time(time_t sec, ngx_uint_t msec) { #if (NGX_HAVE_CLOCK_MONOTONIC)struct timespec ts;#if defined(CLOCK_MONOTONIC_FAST)clock_get…

【Trick】論文畫圖的icon來源

0&#xff1a;起因 群友在群里發了這種很好看的論文主圖 其中不乏有很多icon&#xff0c;比如open-ai、機器人的 于是想知道應該如何找到&#xff0c;便有了后文 1&#xff1a;網址 阿里巴巴矢量圖標庫&#xff1a;iconfont-阿里巴巴矢量圖標庫 2&#xff1a;使用方法 可…

前端 技術棧

前端 技術棧 ChatGPT 說&#xff1a; 好咧&#xff0c;說到前端技術棧&#xff0c;這一塊現在確實百花齊放&#xff0c;有點卷&#xff0c;但也超靈活。下面我來給你梳理一套2025年主流、實用、好上手的前端技術棧組合&#xff0c;按層級分類&#xff0c;一目了然&#xff1a;…

vue3 根據城市名稱計算城市之間的距離

<template><div class"distance-calculator"><h1>城市距離計算器</h1><!-- 城市輸入框 --><div class"input-group"><inputv-model"city1"placeholder"請輸入第一個城市"keyup.enter"cal…

Java安全-FastJson反序列化分析

FastJson介紹 Fastjson 是阿里巴巴推出的一款高性能 JSON 序列化/反序列化庫&#xff0c;由于其便捷性被廣泛應用于 Java 項目中 FastJson使用 package org.example;import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject;public class FastjsonDemo {…

查看npm安裝了哪些全局依賴

查看npm安裝了哪些全局依賴 在macOS上&#xff0c;如果你想要查看通過npm全局安裝的依賴包&#xff0c;你可以使用以下幾種方法&#xff1a; 方法1&#xff1a;使用命令行 打開你的終端&#xff08;Terminal&#xff09;&#xff0c;然后輸入以下命令&#xff1a; npm list -…

告別代碼Bug,GDB調試工具詳解

在軟件開發的漫漫長路上&#xff0c;Bug 就像隱藏在黑暗中的 “小怪獸”&#xff0c;時不時跳出來給開發者們制造麻煩。曾經&#xff0c;歐洲航天局&#xff08;ESA&#xff09;首次發射阿麗亞娜 5 號火箭&#xff0c;這本是太空探索史上的重要時刻&#xff0c;卻因一行代碼導致…

LangChain4j(2):整合SpringBoot

1 新建Springboot項目 1.1 引入依賴 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0…

移動端六大語言速記:第2部分 - 控制結構

移動端六大語言速記&#xff1a;第2部分 - 控制結構 本文繼續對比Java、Kotlin、Flutter(Dart)、Python、ArkTS和Swift這六種移動端開發語言的控制結構&#xff0c;幫助開發者快速掌握各語言的語法差異。 2. 控制結構 2.1 條件語句 各語言條件語句的語法對比&#xff1a; …

Linux-線程概念與線程控制的常用操作

一.Linux線程概念 1-1.線程是什么 在Linux中&#xff0c;線程是基于Linux原有的進程實現的。本質是輕量級進程(LWP)。在?個程序?的?個執?路線就叫做線程&#xff08;thread&#xff09;。更準確的定義是&#xff1a;線程是“?個進程內部的控制序列”。 我們之前所學習的進…