欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 八卦 > RedisServer解析(一)

RedisServer解析(一)

2024/10/24 4:43:45 来源:https://blog.csdn.net/qq_50096311/article/details/140495842  浏览:    关键词:RedisServer解析(一)

文章目录

  • 前言
  • RedisServer
    • getInstance
    • start
  • client
    • client.call
    • net_call
  • handleClient
  • 参考


前言

之前解析了server对buttonrpc的使用,现在分析server是如何接受client发送到信息完成对应的redis操作

RedisServer

getInstance

RedisServer* RedisServer::getInstance()
{static RedisServer redis;return &redis;
}

单例模式中的懒汉模式。因为本项目是单线程项目,不存在多个线程同时调用getinstance的情况,因此不需要额外处理。这里提供在多线程中实现单例模式懒汉模式的方法。

#include <mutex>
class RedisServer {
public:static RedisServer* getInstance();
private:RedisServer();static std::once_flag initFlag; // 用于控制初始化的全局变量
};
std::once_flag RedisServer::initFlag;
RedisServer* RedisServer::getInstance() {static RedisServer* instance = nullptr;std::call_once(initFlag, []() {instance = new RedisServer();});return instance;
}

start

void RedisServer::start() {signal(SIGINT, signalHandler);  printLogo();printStartMessage();
}

注册sigint信号处理函数,sighandler的作用是在使用sigint时将缓冲区刷新一遍。

client

接下来查看server绑定的函数server.bind("redis_command", &RedisServer::handleClient, RedisServer::getInstance());
getinstance是实例,redis_command是map的key值。handleClient则是命令处理函数,client通过此函数 string res = client.call<string>("redis_command", message).val();向server请求。

因此我们接下来查看client的请求过程。

client.call

inline buttonrpc::value_t<R> buttonrpc::call(std::string name, P1 p1)
{Serializer ds;ds << name << p1;return net_call<R>(ds);
}

Serializer对<<进行了重载,在这里就是将name和参数1对内容写入ds.m_iodevice。然后调用net_call。

net_call

template<typename R>
inline buttonrpc::value_t<R> buttonrpc::net_call(Serializer& ds)
{zmq::message_t request(ds.size() + 1);memcpy(request.data(), ds.data(), ds.size());if (m_error_code != RPC_ERR_RECV_TIMEOUT) {send(request);}zmq::message_t reply;recv(reply);value_t<R> val;if (reply.size() == 0) {// timeoutm_error_code = RPC_ERR_RECV_TIMEOUT;val.set_code(RPC_ERR_RECV_TIMEOUT);val.set_msg("recv timeout");return val;}m_error_code = RPC_ERR_SUCCESS;ds.clear();ds.write_raw_data((char*)reply.data(), reply.size());ds.reset();ds >> val;return val;
}

代码比较简答,send(request)将信息发送给服务端,服务端对信息进行处理,其处理逻辑在上一遍博客中已经讲过了。在send和recv之后就是一次信息的处理。在call_函数中有代码段

 auto fun = m_handlers[name]; //获取函数fun(ds, data, len); 

我们知道这其实就是调用了一次handleClient函数。

handleClient

if (!startMulti) {std::shared_ptr<CommandParser> commandParser = flyweightFactory->getParser(command);if (commandParser == nullptr) {responseMessage = "Error: Command '" + command + "' not recognized.";}else {try {responseMessage = commandParser->parse(tokens);}catch (const std::exception& e) {responseMessage = "Error processing command '" + command + "': " + e.what();}}// 发送响应消息回客户端return responseMessage;
}

代码逻辑比较清晰,就是根据输入的command进行不同的操作。一些特殊的命令进行单独处理,而对于常规的命令则采用统一的入口flyweightFactory->getParser(command)。并对返回的信息执行responseMessage = commandParser->parse(tokens);

参考

zeromq

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com