目录
Requestor类的实现
框架
完善
onResponse处理回复
完整代码
RpcCaller类的实现
1. 同步调用 call
2. 异步调用 call
3. 回调调用 call
(1)主要功能:
(2)具体实现:
recv
接口,而是连接触发可读事件后,IO读取数据完成调用处理回调进行数据处理,因此在发送请求后无法直接等待该条请求的响应。解决方案:
namespace bitrpc{
namespace client
{
//客户端 部分
class Requestor
{
public:
using ptr = std::shared_ptr;
using RequestCallback = std::function;
using AsyncResponse = std::future;
struct RequestDescribe
{
using ptr=std::shared_ptr;//智能指针 管理
};
//请求 信息描述
//之后 好调用 所需要的rsp函数
//Dispatcher调用
void onResponse(const BaseConnection::ptr &conn,BaseMessage::ptr &msg)
{
}
//异步发送
bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, AsyncResponse &async_rsp)
{}
//同步发送
bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, BaseMessage::ptr &rsp)
{}
//回调发送
bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, const RequestCallback &cb)
{}
private:
//对于 请求 描述进行CURD
//增
RequestDescribe::ptr newDescribe(const BaseMessage::ptr &req, RType rtype,
const RequestCallback &cb = RequestCallback()) {}
//查 rid
RequestDescribe::ptr getDescribe(const std::string &rid)
{}
//删
void delDescribe(const std::string &rid)
{}
private:
std::mutex _mutex;
std::unordered_map _request_desc;
};
}
}
信息描述
struct RequestDescribe {
using ptr = std::shared_ptr;
BaseMessage::ptr request;
RType rtype;
std::promise response;
RequestCallback callback;
};
对收到的响应 通过 uid ,对应上是哪个请求发出的
实现了上面的解决问题
void onResponse(const BaseConnection::ptr &conn, BaseMessage::ptr &msg){
std::string rid = msg->rid();
RequestDescribe::ptr rdp = getDescribe(rid);
//根据先获取msg->rid() 来进行结果的调用
if (rdp.get() == nullptr) {
ELOG("收到响应 - %s,但是未找到对应的请求描述!", rid.c_str());
return;
}
if (rdp->rtype == RType::REQ_ASYNC) {
rdp->response.set_value(msg);//调用 不同的接口
}else if (rdp->rtype == RType::REQ_CALLBACK){
if (rdp->callback) rdp->callback(msg);
}else {
ELOG("请求类型未知!!");
}
delDescribe(rid);
}
onResponse
处理回复onResponse
方法是对收到的消息进行处理的入口点。当收到服务器的响应时,该方法会被调用来匹配相应的请求描述(RequestDescribe
),并通过请求类型(RType
)来决定如何处理响应:RType::REQ_ASYNC
),则通过设置std::promise
的值(response.set_value(msg)
)来完成对应的std::future
,使得调用者可以通过未来对象获取响应。RType::REQ_CALLBACK
),则直接调用注册的回调函数(rdp->callback(msg)
)来处理响应。onResponse
方法则是 对接收到的响应进行处理,
关于 promise set_value: C++11 异步操作 future类_文档学习
send
方法负责构建和发送请求,
//异步操作
bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, AsyncResponse &async_rsp)
{
RequestDescribe::ptr rdp = newDescribe(req, RType::REQ_ASYNC);
if (rdp.get() == nullptr)
{
ELOG("构造请求描述对象失败!");
return false;
}
conn->send(req);
async_rsp = rdp->response.get_future();
return true;
}
//同步操作
bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, BaseMessage::ptr &rsp)
{
AsyncResponse rsp_future;
bool ret = send(conn, req, rsp_future);
if (ret == false)
{
return false;
}
rsp = rsp_future.get();
return true;
}
//回调函数
bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, const RequestCallback &cb)
{
RequestDescribe::ptr rdp = newDescribe(req, RType::REQ_CALLBACK, cb);
if (rdp.get() == nullptr)
{
ELOG("构造请求描述对象失败!");
return false;
}
conn->send(req);//!!!!!!!!!!!!!!!!
return true;
}
1.
前文回顾:[C++#28][多态] 两个条件 | 虚函数表 | 抽象类 | override 和 final | 重载 重写 重定义
Requestor
类中的 三个重载send
方法,这些方法用于通过指定的连接对象发送消息
同:
send
方法都接受两个相同的基本参数:一个指向BaseConnection
的智能指针conn
(表示网络连接)和一个指向BaseMessage
的智能指针req
(表示要发送的消息)。send
方法在无法成功创建请求描述对象时,都会记录错误日志并返回false
,指示操作失败。conn->send(req)
来执行实际的消息发送。异:
send
方法(有三个重载版本)用于通过网络连接conn
发送请求消息req
到服务器:send
方法接受一个AsyncResponse &async_rsp
参数,用于异步发送请求并返回一个std::future
对象,以便于后续获取响应。(不阻塞send
方法是同步的,它 等待直到接收到服务器的响应并将结果赋值给BaseMessage::ptr &rsp
。send
方法允许用户在发送请求时提供一个回调函数const RequestCallback &cb
,当收到响应时会自动调用该回调进行处理。(send 后,就不管了,不会阻塞等待)对比第一种和第三种方式:
future.get()
获取结果,可能导致阻塞。private:
// 对于 请求 描述进行CURD
//增
RequestDescribe::ptr newDescribe(const BaseMessage::ptr &req, RType rtype,
const RequestCallback &cb = RequestCallback())
{
std::unique_lock lock(_mutex);
//加锁
RequestDescribe::ptr rd = std::make_shared();
rd->request = req;
rd->rtype = rtype;
if (rtype == RType::REQ_CALLBACK && cb)
{
rd->callback = cb;
}
_request_desc.insert(std::make_pair(req->GetId(), rd));
//将id 和描述 进行对应
return rd;
}
//查
RequestDescribe::ptr getDescribe(const std::string &rid)
{
std::unique_lock lock(_mutex);
auto it = _request_desc.find(rid);
if (it == _request_desc.end())
{
return RequestDescribe::ptr();
}
return it->second;
}
//删
void delDescribe(const std::string &rid)
{
std::unique_lock lock(_mutex);
_request_desc.erase(rid);
}
#pragma once
#include "../common/net.hpp"
#include "../common/message.hpp"
#include //异步操作
#include //1.灵活的函数使用 bind function
namespace bitrpc{
namespace client
{
//客户端 部分
class Requestor
{
public:
using ptr = std::shared_ptr;
using RequestCallback = std::function;
using AsyncResponse = std::future;//异步处理信息
struct RequestDescribe {
using ptr = std::shared_ptr;
BaseMessage::ptr request;
RType rtype;
std::promise response;
RequestCallback callback;
};
//请求 信息描述
//之后 好调用 所需要的rsp函数
//Dispatcher 给RSP_RPC回复调用的
void onResponse(const BaseConnection::ptr &conn, BaseMessage::ptr &msg){
std::string rid = msg->GetId();
RequestDescribe::ptr rdp = getDescribe(rid);
if (rdp.get() == nullptr) {
ELOG("收到响应 - %s,但是未找到对应的请求描述!", rid.c_str());
return;
}
if (rdp->rtype == RType::REQ_ASYNC) {
rdp->response.set_value(msg);
}else if (rdp->rtype == RType::REQ_CALLBACK){
if (rdp->callback) rdp->callback(msg);
}else {
ELOG("请求类型未知!!");
}
delDescribe(rid);
}
//!!!!!!!对收到 的回复请求 进行id存储
//异步详可见demo中的 使用
//异步操作
bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, AsyncResponse &async_rsp)
{
RequestDescribe::ptr rdp = newDescribe(req, RType::REQ_ASYNC);
if (rdp.get() == nullptr)
{
ELOG("构造请求描述对象失败!");
return false;
}
conn->send(req);
async_rsp = rdp->response.get_future();
return true;
}
//同步操作
bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, BaseMessage::ptr &rsp)
{
AsyncResponse rsp_future;
bool ret = send(conn, req, rsp_future);
if (ret == false)
{
return false;
}
rsp = rsp_future.get();
return true;
}
//回调函数
bool send(const BaseConnection::ptr &conn, const BaseMessage::ptr &req, const RequestCallback &cb)
{
RequestDescribe::ptr rdp = newDescribe(req, RType::REQ_CALLBACK, cb);
if (rdp.get() == nullptr)
{
ELOG("构造请求描述对象失败!");
return false;
}
conn->send(req);
return true;
}
//
private:
// CURD
//增
RequestDescribe::ptr newDescribe(const BaseMessage::ptr &req, RType rtype,
const RequestCallback &cb = RequestCallback())
{
std::unique_lock lock(_mutex);
RequestDescribe::ptr rd = std::make_shared();
rd->request = req;
rd->rtype = rtype;
if (rtype == RType::REQ_CALLBACK && cb)
{
rd->callback = cb;
}
_request_desc.insert(std::make_pair(req->GetId(), rd));
//将id 和描述 进行对应
return rd;
}
//查
RequestDescribe::ptr getDescribe(const std::string &rid)
{
std::unique_lock lock(_mutex);
auto it = _request_desc.find(rid);
if (it == _request_desc.end())
{
return RequestDescribe::ptr();
}
return it->second;
}
//删
void delDescribe(const std::string &rid)
{
std::unique_lock lock(_mutex);
_request_desc.erase(rid);
}
private:
std::mutex _mutex;
std::unordered_map _request_desc;
};
}
}
(Requestor 的处理 调用 RpcCaller)
(1)主要功能:
(2)具体实现:
❗❗❗❗
// requestor中的处理是针对BaseMessage进行处理的
// 用于在rpccaller中针对结果的处理是针对 RpcResponse里边的result进行的
#pragma once
#include "requestor.hpp"
// request 有 rpc topic server
// 其中 rpc部分的 调用函数的 实现
namespace bitrpc
{
namespace client
{
class RpcCaller
{
public:
using ptr = std::shared_ptr;
using JsonAsyncResponse = std::future;
using JsonResponseCallback = std::function;
RpcCaller(const Requestor::ptr &requestor) : _requestor(requestor) {}
// requestor中的处理是针对BaseMessage进行处理的
// 用于在rpccaller中针对结果的处理是针对 RpcResponse里边的result进行的
//1.
bool call(const BaseConnection::ptr &conn, const std::string &method,
const Json::Value ¶ms, Json::Value &result)
{
DLOG("开始同步rpc调用...");
// 1. 组织请求
auto req_msg = MessageFactory::create();
req_msg->SetId(UUID::uuid());
req_msg->setMethod(method);
req_msg->setParams(params);
req_msg->SetMType(MType::REQ_RPC);
BaseMessage::ptr rsp_msg;
// 2. 发送请求
bool ret = _requestor->send(conn, std::dynamic_pointer_cast(req_msg), rsp_msg);
if (ret == false)
{
ELOG("同步Rpc请求失败!");
return false;
}
DLOG("收到响应,进行解析,获取结果!");
// 3. 等待响应
auto rpc_rsp_msg = std::dynamic_pointer_cast(rsp_msg);
if (!rpc_rsp_msg)
{
ELOG("rpc响应,向下类型转换失败!");
return false;
}
if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
{
ELOG("rpc请求出错:%s", errReason(rpc_rsp_msg->rcode()));
return false;
}
result = rpc_rsp_msg->result();
DLOG("结果设置完毕!");
return true;
}
/
/
//2.
bool call(const BaseConnection::ptr &conn, const std::string &method,
const Json::Value ¶ms, JsonAsyncResponse &result)
{
// 向服务器发送异步回调请求,设置回调函数,回调函数中会传入一个promise对象,在回调函数中去堆promise设置数据
auto req_msg = MessageFactory::create();
req_msg->SetId(UUID::uuid());
req_msg->SetMType(MType::REQ_RPC);
req_msg->setMethod(method);
req_msg->setParams(params);
auto json_promise = std::make_shared>();
result = json_promise->get_future();
Requestor::RequestCallback cb = std::bind(&RpcCaller::Callback,
this, json_promise, std::placeholders::_1);
bool ret = _requestor->send(conn, std::dynamic_pointer_cast(req_msg), cb);
if (ret == false)
{
ELOG("异步Rpc请求失败!");
return false;
}
return true;
}
//3.
bool call(const BaseConnection::ptr &conn, const std::string &method,
const Json::Value ¶ms, const JsonResponseCallback &cb)
{
auto req_msg = MessageFactory::create();
req_msg->SetId(UUID::uuid());
req_msg->SetMType(MType::REQ_RPC);
req_msg->setMethod(method);
req_msg->setParams(params);
Requestor::RequestCallback req_cb = std::bind(&RpcCaller::Callback1,
this, cb, std::placeholders::_1);
bool ret = _requestor->send(conn, std::dynamic_pointer_cast(req_msg), req_cb);
if (ret == false)
{
ELOG("回调Rpc请求失败!");
return false;
}
return true;
}
private:
void Callback1(const JsonResponseCallback &cb, const BaseMessage::ptr &msg)
{
auto rpc_rsp_msg = std::dynamic_pointer_cast(msg);
if (!rpc_rsp_msg)
{
ELOG("rpc响应,向下类型转换失败!");
return;
}
if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
{
ELOG("rpc回调请求出错:%s", errReason(rpc_rsp_msg->rcode()));
return;
}
cb(rpc_rsp_msg->result());
}
void Callback(std::shared_ptr> result, const BaseMessage::ptr &msg)
{
auto rpc_rsp_msg = std::dynamic_pointer_cast(msg);
if (!rpc_rsp_msg)
{
ELOG("rpc响应,向下类型转换失败!");
return;
}
if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
{
ELOG("rpc异步请求出错:%s", errReason(rpc_rsp_msg->rcode()));
return;
}
result->set_value(rpc_rsp_msg->result());
}
private:
Requestor::ptr _requestor;
};
}
}
RpcCaller
类中 三个重载的call
方法,这些方法提供了不同的方式来发起RPC调用,并处理从服务器返回的响应。每个call
方法根据其参数和使用场景的不同,具有特定的功能和适用性:
1. 同步调用
call
RpcRequest
消息。_requestor->send()
发送请求,并阻塞等待响应。result
中 返回给调用者。2. 异步调用
call
std::future
机制获取结果。RpcRequest
消息。Callback
用于在接收到响应时设置std::promise
的值。_requestor->send()
发送请求,并立即返回(非阻塞)。result.get()
在未来某个时刻获取。3. 回调调用
call
RpcRequest
消息。Callback1
,该回调会在接收到响应时被调用,并进一步调用用户提供的回调函数处理结果。_requestor->send()
发送请求,并立即返回(非阻塞)。本节重点,通过 重载 来实现同步 回调 异步