RpcChannel的调用过程
目录
1. RPC调用方(caller)的调用(消费)过程
2.在caller下创建文件:calluserservice.cc
3.在src的include下创建文件:mprpcchannel.h
4.在src下创建mprpcchannel.cc
1. RPC调用方(caller)的调用(消费)过程
caller就是按照提供rpc服务的那一方(callee)提供的proto协议,发起调用
2.在caller下创建文件:calluserservice.cc
#include <iostream>
#include "mprpcapplication.h"
#include "user.pb.h"
#include "mprpcchannel.h"int main(int argc,char** argv)
{//整个程序启动以后,想使用mprpc框架来享受rpc服务调用,一定需要先调用框架的初始化函数(只初始化一次)MprpcApplication::Init(argc,argv);//演示调用远程发布的rpc方法Loginfixbug::UserServiceRpc_Stub stub(new MprpcChannel());//rpc方法的请求参数fixbug::LoginRequest request;request.set_name("zhang san");request.set_pwd("123456");//rpc方法的响应fixbug::LoginResponse response;//发起rpc方法的调用 同步的rpc调用过程 MprpcChannel::callmethodstub.Login(nullptr,&request,&response,nullptr);//RpcChannel->RpcChannel::callMethod 集中来做所有rpc方法调用的参数序列化和网络发送//一次rpc调用完成,读调用的结果if(0==response.result().errcode()){std::cout<<"rpc login response success:"<<response.success()<<std::endl;}else{std::cout<<"rpc login response error:"<<response.result().errmsg()<<std::endl;}return 0;
}
UserServiceRpc_Stub的构造函数必须要有RpcChannel参数
我们知道,里面那些方法最终都是调用channel的CallMethod方法。
这个RpcChannel是一个抽象类,new不了对象,我们得在框架上定义一个类从RpcChannel继承而来,然后重写CallMethod方法。
所以,我们现在要在框架上写代码,针对RPC的调用方。
3.在src的include下创建文件:mprpcchannel.h
#pragma once#include <google/protobuf/service.h>class MprpcChannel:public google::protobuf::RpcChannel
{
public://所有通过stub代理对象调用的rpc方法,都走到这里了,统一做rpc方法调用的数据的数据序列化和网络发送void CallMethod(const google::protobuf::MethodDescriptor* method,google::protobuf::RpcController* controller,const google::protobuf::Message* request,google::protobuf::Message* response,google::protobuf::Closure* done);
};
在example下的caller下创建CMakeLists.txt
set(SRC_LIST calluserservice.cc ../user.pb.cc)
add_executable(consumer ${SRC_LIST})#可执行文件#链接库文件
target_link_libraries(consumer mprpc protobuf)
4.在src下创建mprpcchannel.cc
#include "mprpcchannel.h"
#include "rpcheader.pb.h"
#include "mprpcapplication.h"#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>/*
header_size+service_name method_name args_size+args
*/
// 所有通过stub代理对象调用的rpc方法,都走到这里了,统一做rpc方法调用的数据的数据序列化和网络发送
void MprpcChannel::CallMethod(const google::protobuf::MethodDescriptor *method,google::protobuf::RpcController *controller,const google::protobuf::Message *request,google::protobuf::Message *response,google::protobuf::Closure *done)
{const google::protobuf::ServiceDescriptor* sd=method->service();std::string service_name=sd->name();//service_namestd::string method_name=method->name();//method_name//获取参数的序列化字符串长度 args_sizeuint32_t args_size=0;std::string args_str;if(request->SerializeToString(&args_str)){args_size=args_str.size();}else{std::cout<<"serialize request error!"<<std::endl;return;}//定义rpc的请求headermprpc::RpcHeader rpcHeader;rpcHeader.set_service_name(service_name);rpcHeader.set_method_name(method_name);rpcHeader.set_args_size(args_size);uint32_t header_size=0;std::string rpc_header_str;if(rpcHeader.SerializeToString(&rpc_header_str)){header_size=rpc_header_str.size();}else{std::cout<<"serialize request error!"<<std::endl;return;}//组织待发送的rpc请求的字符串std::string send_rpc_str;send_rpc_str.insert(0,std::string((char*)&header_size,4));//header_sizesend_rpc_str+=rpc_header_str;//rpcheadersend_rpc_str+=args_str;//args//打印调试信息std::cout<<"===================================================="<<std::endl;std::cout<<"header_size:"<<header_size<<std::endl;std::cout<<"rpc_header_str:"<<rpc_header_str<<std::endl;std::cout<<"service_name:"<<service_name<<std::endl;std::cout<<"method_name:"<<method_name<<std::endl;std::cout<<"args_str:"<<args_str<<std::endl;std::cout<<"===================================================="<<std::endl;//使用tcp编程,完成rpc方法的远程调用int clientfd=socket(AF_INET,SOCK_STREAM,0);if(-1==clientfd){std::cout<<"create socket error! errno:"<<errno<<std::endl;exit(EXIT_FAILURE);}//读取配置文件rpcsever的信息std::string ip=MprpcApplication::GetInstance().GetConfig().Load("rpcserverip");uint16_t port=atoi(MprpcApplication::GetInstance().GetConfig().Load("rpcserverport").c_str());struct sockaddr_in server_addr;server_addr.sin_family=AF_INET;server_addr.sin_port=htons(port);server_addr.sin_addr.s_addr=inet_addr(ip.c_str());//连接rpc服务节点if(-1==connect(clientfd,(struct sockaddr*)&server_addr,sizeof(server_addr))){std::cout<<"connect error! errno:"<<errno<<std::endl;close(clientfd);exit(EXIT_FAILURE);}//发送rpc请求if(-1==send(clientfd,send_rpc_str.c_str(),send_rpc_str.size(),0)){std::cout<<"send error! errno:"<<errno<<std::endl;close(clientfd);return;}//接收rpc请求的响应值char recv_buf[1024]={0};int recv_size=0;if(-1==(recv_size=recv(clientfd,recv_buf,1024,0))){std::cout<<"recv error! errno:"<<errno<<std::endl;close(clientfd);return;}std::string response_str(recv_buf,0,recv_size);if(response->ParseFromString(response_str)){std::cout<<"parse error! response_str:"<<response_str<<std::endl;close(clientfd);return;}close(clientfd);
}
相关文章:

RpcChannel的调用过程
目录 1. RPC调用方(caller)的调用(消费)过程 2.在caller下创建文件:calluserservice.cc 3.在src的include下创建文件:mprpcchannel.h 4.在src下创建mprpcchannel.cc 1. RPC调用方(caller)的调用(消费)过…...

东芝TB6560AHQ/AFG步进电机驱动IC:解锁卓越的电机控制性能
作为一名工程师,一直在寻找可靠且高效的组件来应用于你的项目中。东芝的TB6560AHQ/AFG步进电机驱动IC能够提供精准且多功能的电机控制,完全符合现代应用的高要求,保证高性能和易用性。在这篇文章中,我们将探讨TB6560AHQ/AFG的主要…...

免杀笔记 ----> DLL注入
这段时间我们暂时没什么事情干的话我们就继续更新我们的免杀笔记力!!! :今天我们讲DLL注入 目录 1.DLL注入 2.直接加载DLL? 3.远程线程注入 获取Handle 远程申请内存空间 将我们的CS的DLL加载入内存 创建远程线…...

奇迹MU 骷髅战士在哪
BOSS分布图介绍 我为大家带来各地区怪物分布图。在游戏前期,很多玩家可能会不知道该去哪里寻找怪物,也不知道哪些怪物值得打。如果选择了太强的怪物,弱小的玩家可能会无法抵御攻击。如果选择了低等级的boss,收益可能并不理想。所…...

leetcode力扣_贪心思想
455.分发饼干(easy-自己想得出来并写好) 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺…...

Vue中Class数据绑定
Class数据绑定 数据绑定的一个常见需求场景是操作CSS class列表,因为class是attribute(属性),我们可以和其他attribute一样使用v-bind 将它们和动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接生…...

Python数据分析案例49——基于机器学习的垃圾邮件分类系统构建(朴素贝叶斯,支持向量机)
案例背景 trec06c是非常经典的邮件分类的数据,还是难能可贵的中文数据集。 这个数据集从一堆txt压缩包里面提取出来整理为excel文件还真不容不易,肯定要做一下文本分类。 虽然现在文本分类基本都是深度学习了,但是传统的机器学习也能做。本案…...
贪心算法-以学籍管理系统为例
1.贪心算法介绍 1.算法思路 贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一 步都要确保能获得局部最优解。每一步只考虑一 个数据,其选取应该满足局部优化的条件。若下 一个数据和部分最优解连在一起…...
PyCharm 安装
PyCharm是一种流行的Python集成开发环境(IDE),由JetBrains公司开发。它提供了丰富的功能,如智能代码补全、实时错误检查、项目导航、调试工具以及版本控制等,极大地提高了Python开发人员的工作效率。以下是PyCharm安装…...
C++:对象指针访问成员函数
使用箭头操作符 (->):ptr->function() 是最常用和推荐的方式,因为它更简洁、更直观。箭头操作符 (->) 被设计为与点操作符 (.) 配合指针一起使用,以便通过指针访问对象的成员。 先解引用指针,然后使用点操作符 (.)&…...

Linux 防火墙配置指南:firewalld 端口管理应用案例(二十个实列)
🏡作者主页:点击! 🐧Linux基础知识(初学):点击! 🐧🐧Linux高级管理专栏:点击! 🔐Linux中firewalld防火墙:点击! ⏰️…...

推荐Bulk Image Downloader插件下载网页中图片链接很好用
推荐:Bulk Image Downloader chome浏览器插件下载图片链接,很好用。 有个网页,上面放了数千的gif的电路图,手工下载会累瘫了不可。想找一个工具分析它的静态链接并下载,找了很多推荐的下载工具,都是不能分…...
详解前缀码与前缀编码
前缀编码是一种数据压缩技术,也被称为可变长度编码。它的基本原理是将频繁出现的字符或字符序列用较短的编码表示,而较少出现的字符或字符序列用较长的编码表示,从而达到压缩数据的目的。 概念定义 前缀码:给定一个编码序列的集合…...

数据库管理工具 -- Navicat Premium v17.0.8 特别版
软件简介 Navicat Premium 是一款功能强大的数据库管理工具,适用于Windows、Mac和Linux平台。它支持多种数据库,包括MySQL、MariaDB、SQL Server、PostgreSQL、Oracle、SQLite等。用户可以通过Navicat Premium轻松地连接到各种数据库服务器,…...

【Linux】进程创建和终止 | slab分配器
进程创建 fork 1.fork 之后发生了什么 将给子进程分配新的内存块和内核数据结构(形成了新的页表映射)将父进程部分数据结构内容拷贝至子进程添加子进程到系统进程列表当中fork 返回,开始调度器调度 这样就可以回答之前返回两个值?…...

计算机网络--网络层
一、网络层的服务和功能 网络层主要为应用层提供端对端的数据传输服务 网络层接受运输层的报文段,添加自己的首部,形成网络层分组。分组是网络层的传输单元。网络层分组在各个站点的网络层之间传输,最终到达接收方的网络层。接收方网络层将运…...
【CSS】如何实现分栏布局
在CSS分栏布局中,设置宽度和样式是一个基本且重要的步骤。这可以通过直接应用样式到列元素(通常是div元素)上来实现。以下是一些常用的方法来设置分栏布局的宽度和样式: 1. 使用百分比宽度 使用百分比宽度可以使列的大小相对于其…...

2025湖北武汉智慧教育装备信息化展/智慧校园展/湖北高博会
2025武汉教育装备展,2025武汉智慧教育展,2025武汉智慧校园展,2025武汉教育信息化展,2025武汉智慧教室展,湖北智慧校园展,湖北智慧教室展,武汉教学设备展,湖北高教会,湖北高博会 2025湖北武汉智慧教育装备信息化展/智慧校园展/湖北高博会 2025第10届武汉国际教育装备及智慧校园…...

Android Studio Run窗口中文乱码解决办法
Android Studio Run窗口中文乱码解决办法 问题描述: AndroidStudio 编译项目时Run窗口中文乱码,如图: 解决方法: 依次打开菜单:Help--Edit Custom VM Options,打开studio64.exe.vmoptions编辑框…...

代码随想录——划分字母区间(Leetcode763)
题目链接 贪心 class Solution {public List<Integer> partitionLabels(String s) {int[] count new int[27];Arrays.fill(count,0);// 统计元素最后一次出现的位置for(int i 0; i < s.length(); i){count[s.charAt(i) - a] i;}List<Integer> res new Ar…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...