目录
1.回顾测试
2.mprpc框架的配置文件加载
2.1 mprpcconfig.h
2.2 完善mprpcapplication.h
2.3 完善mprpcapplication.cc
2.4 mprpcconfig.cc
2.5 test.conf
2.6 测试运行
3.扩展问题
1.回顾测试
我们先把之前的项目代码工程编译好,然后进入bin里面,执行
./provider
显示我们之前编的代码正确了!
接下来,我们开始编写配置文件
2.mprpc框架的配置文件加载
一开始编写的代码,读取配置文件信息时没有处理好,导致打印结果有多余的空行。
调试信息如下:
由上图可见是多读了一个\n导致的,更改后如下:
2.1 mprpcconfig.h
在src的include中创建头文件:mprpcconfig.h
#pragma once#include <unordered_map>
#include <string>//rpcserverip rpcserverport zookeeperip zookeeperport
//框架读取配置文件类
class MprpcConfig
{
public://负责解析加载配置文件void LoadConfigFile(const char* config_file);//查询配置项信息std::string Load(const std::string& key);//返回key所对应的值-字符串
private:std::unordered_map<std::string,std::string> m_configMap;//去掉字符串前后的空格void Trim(std::string& src_buf);
};
2.2 完善mprpcapplication.h
#pragma once
#include "mprpcconfig.h"//mprpc框架的基础类,负责框架的一些初始化操作
class MprpcApplication
{
public:static void Init(int argc,char** argv);//初始化//单例模式static MprpcApplication& GetInstance();//定义获取唯一实例的方法private:static MprpcConfig m_config;MprpcApplication(){}//构造函数MprpcApplication(const MprpcApplication&)=delete;//将与拷贝构造有关的函数deleteMprpcApplication(MprpcApplication&&) = delete;
};
2.3 完善mprpcapplication.cc
#include "mprpcapplication.h"
#include <iostream>
#include <unistd.h>MprpcConfig MprpcApplication::m_config;void ShowArgsHelp()
{std::cout<<"format: command -i <configfile>"<<std::endl;
}void MprpcApplication::Init(int argc, char **argv) // 初始化
{if(argc<2){ShowArgsHelp();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 '?'://std::cout<<"invalid args!"<<std::endl;ShowArgsHelp();exit(EXIT_FAILURE);case ':'://std::cout<<"need <configfile>"<<std::endl;ShowArgsHelp();exit(EXIT_FAILURE);default:break;}}//开始加载配置文件了 rpcserver_ip= rpcserver_port zookeeper_ip= zookeeper_port=m_config.LoadConfigFile(config_file.c_str());// std::cout<<"rpcserverip:"<<m_config.Load("rpcserverip")<<std::endl;// std::cout<<"rpcserverport:"<<m_config.Load("rpcserverport")<<std::endl;// std::cout<<"zookeeperip:"<<m_config.Load("zookeeperip")<<std::endl;// std::cout<<"zookeeperport:"<<m_config.Load("zookeeperport")<<std::endl;
}
// 单例模式
MprpcApplication &MprpcApplication::GetInstance() // 定义获取唯一实例的方法
{static MprpcApplication app;return app;
}
2.4 mprpcconfig.cc
在src下创建文件mprpcconfig.cc
#include "mprpcconfig.h"#include <iostream>//负责解析加载配置文件
void MprpcConfig::LoadConfigFile(const char* config_file)
{FILE* pf=fopen(config_file,"r");if(nullptr==pf){std::cout<<config_file<<" is note exist!"<<std::endl;exit(EXIT_FAILURE);}//1.注释 2.正确的配置项 = 3.去掉开头的多余空格while(!feof(pf)){char buf[512]={0};fgets(buf,512,pf);//去掉字符串前面多余的空格std::string read_buf(buf);Trim(read_buf);//判断#的注释if(read_buf[0]=='#'||read_buf.empty()){continue;}//解析配置项int idx=read_buf.find('=');if(idx==-1){//配置项不合法continue;}std::string key;std::string value;key=read_buf.substr(0,idx);Trim(key);//rpcserverip=127.0.0.1\n int endidx=read_buf.find('\n',idx);//从等号之后开始寻找\nvalue=read_buf.substr(idx+1,endidx-idx-1);Trim(value);m_configMap.insert({key,value});}
}// 查询配置项信息
std::string MprpcConfig::Load(const std::string &key)
{//return m_configMap[key];//不要使用[],会产生副作用,正常情况key如果不存在,会返回空,可是用[]的话,会在map表中增加一对值auto it=m_configMap.find(key);if(it==m_configMap.end()){return "";}return it->second;
}void MprpcConfig::Trim(std::string &src_buf)
{int idx = src_buf.find_first_not_of(' ');if (idx != -1){// 说明字符串前面有空格src_buf = src_buf.substr(idx, src_buf.size() - idx); // 第一个参数是下标,第二个是长度}// 去掉字符串后面多余的空格idx = src_buf.find_last_not_of(' ');if (idx != -1){// 说明字符串后面有空格src_buf = src_buf.substr(0, idx + 1);}
}
2.5 test.conf
在bin下创建一个配置文件:test.conf
#rpc节点的ip地址
rpcserverip=127.0.0.1
#rpc节点的port端口号
rpcserverport=8000
#zk的ip地址
zookeeperip=127.0.0.1
#zk的port端口号
zookeeperport=5000
2.6 测试运行
编译:
测试结果:
3.扩展问题
C++中的容器都不是线程安全的,需要解决这个问题吗?
不需要考虑线程安全,因为整个提供rpc服务的站点启动以后,框架只需要init一次,不需要多线程。为了防止框架被多次初始化,可以在mprpcapplication.h文件中添加一个静态变量,来记录框架是否被初始化。