【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.mzph.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;线程是“⼀个进程内部的控制序列”。 我们之前所学习的进…