RpcApplication
本章讲解第一个核心类RpcApplication
, 该类的主要任务是解析传入的配置文件, 并可以取出解析到的内容, 简单来说就是执行初始化任务.
为什么要传入并解析配置文件?
网络通信是点到点的, 你必须要知道对端的ip和port才能真正实现通信. 在本框架中, 配置文件主要存储的就是我们的目标服务器的ip与port, 当然如果我们使用zookeeper, 也会存储对应zk的ip与port, 关于zk我们之后再讲.
那么在认识了what和why后, 对于配置文件的解析其实就是很普通的字符串处理了, 让我们通过代码来了解 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #pragma once #include "mprpcconfig.h" #include "mprpcchannel.h" #include "mprpccontroller.h" class MprpcApplication {public : static void Init (int argc, char *argv[]) ; static MprpcApplication &GetInstance () ; static MprpcConfig &getConfig () ;private : MprpcApplication () {} MprpcApplication (const MprpcApplication &) = delete ; MprpcApplication (MprpcApplication &&) = delete ; static MprpcConfig _config; };
init : 不管是客户端还是服务端, 在最初构造完MprpcApplication对象后都要调用此函数, 用来加载配置文件.
GetInstance : 本类采取单例模式, 因为获取配置始终只需要一个对象即可, 唯一对象都通过该函数获取.
getConfig : 获取解析完成的配置对象.
_config : 配置对象, 之后会分析.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include "mprpcapplication.h" #include <iostream> using std::cout;using std::endl;#include <unistd.h> MprpcConfig MprpcApplication::_config;MprpcApplication &MprpcApplication::GetInstance () { static MprpcApplication app; return app; }void MprpcApplication::Init (int argc, char *argv[]) { if (argc < 2 ) { cout << "format: command -i <configfile>" << endl; exit (EXIT_FAILURE); } int c = 0 ; std::string config_file; while ((c = getopt (argc, argv, "i:" )) != -1 ) { switch (c) { case 'i' : config_file = optarg; break ; case '?' : exit (EXIT_FAILURE); case ':' : exit (EXIT_FAILURE); default : break ; } } _config.LoadConfigFile (config_file.c_str ()); std::cout << "rpcserverip:" << _config.Load ("rpcserverip" ) << std::endl; std::cout << "rpcserverport:" << _config.Load ("rpcserverport" ) << std::endl; std::cout << "zookeeperip:" << _config.Load ("zookeeperip" ) << std::endl; std::cout << "zookeeperport:" << _config.Load ("zookeeperport" ) << std::endl; }MprpcConfig &MprpcApplication::getConfig () { return _config; }
MprpcApplication
只负责对传入的参数进行合法性检验并执行生成配置对象, 真正的细节在MprpcConfig中.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #pragma once #include <iostream> #include <unordered_map> class MprpcConfig {public : void LoadConfigFile (const char *config_file) ; std::string Load (const std::string &key) ;private : std::unordered_map<std::string, std::string> _configMap; };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include "mprpcconfig.h" #include <string> void MprpcConfig::LoadConfigFile (const char *config_file) { FILE *pf = fopen (config_file, "r" ); if (nullptr == pf) { exit (EXIT_FAILURE); } while (!feof (pf)) { char buf[512 ] = {0 }; fgets (buf, 512 , pf); std::string sbuf (buf) ; for (int i = 0 ; i < sbuf.size (); i++) { if (sbuf[i] == ' ' || sbuf[i] == '\r' || sbuf[i] == '\n' ) sbuf.erase (i, 1 ), i--; } if (sbuf[0 ] == '#' ) continue ; int idx = sbuf.find ('=' ); std::string key = sbuf.substr (0 , idx); std::string value = sbuf.substr (idx + 1 ); _configMap[key] = value; } }std::string MprpcConfig::Load (const std::string &key) { if (_configMap.count (key) == 0 ) return "" ; return _configMap[key]; }
LoadConfigFile :
在该函数中, 通过传入的配置文件路径打开文件并进行字符串处理, 将每个键值对存入_configMap
.
Load :
该函数用于查询, 传入代表键的string, 就会返回解析出来的值string.
经过这样子解析配置文件, 我们就可以通过类似下面的操作取出配置文件中的参数 :
1 2 std::string ip = MprpcApplication::GetInstance ().getConfig ().Load ("rpcserverip" ); std::string port = MprpcApplication::GetInstance ().getConfig ().Load ("rpcserverport" );
by 天目中云