【Lars教程目錄】
Lars源代碼
https://github.com/aceld/Lars
【Lars系統(tǒng)概述】
第1章-概述
第2章-項目目錄構建
【Lars系統(tǒng)之Reactor模型服務器框架模塊】
第1章-項目結構與V0.1雛形
第2章-內(nèi)存管理與Buffer封裝
第3章-事件觸發(fā)EventLoop
第4章-鏈接與消息封裝
第5章-Client客戶端模型
第6章-連接管理及限制
第7章-消息業(yè)務路由分發(fā)機制
第8章-鏈接創(chuàng)建/銷毀Hook機制
第9章-消息任務隊列與線程池
第10章-配置文件讀寫功能
第11章-udp服務與客戶端
第12章-數(shù)據(jù)傳輸協(xié)議protocol buffer
第13章-QPS性能測試
第14章-異步消息任務機制
第15章-鏈接屬性設置功能
【Lars系統(tǒng)之DNSService模塊】
第1章-Lars-dns簡介
第2章-數(shù)據(jù)庫創(chuàng)建
第3章-項目目錄結構及環(huán)境構建
第4章-Route結構的定義
第5章-獲取Route信息
第6章-Route訂閱模式
第7章-Backend Thread實時監(jiān)控
【Lars系統(tǒng)之Report Service模塊】
第1章-項目概述-數(shù)據(jù)表及proto3協(xié)議定義
第2章-獲取report上報數(shù)據(jù)
第3章-存儲線程池及消息隊列
【Lars系統(tǒng)之LoadBalance Agent模塊】
第1章-項目概述及構建
第2章-主模塊業(yè)務結構搭建
第3章-Report與Dns Client設計與實現(xiàn)
第4章-負載均衡模塊基礎設計
第5章-負載均衡獲取Host主機信息API
第6章-負載均衡上報Host主機信息API
第7章-過期窗口清理與過載超時(V0.5)
第8章-定期拉取最新路由信息(V0.6)
第9章-負載均衡獲取Route信息API(0.7)
第10章-API初始化接口(V0.8)
第11章-Lars Agent性能測試工具
第12章- Lars啟動工具腳本
11) 配置文件讀寫功能
? 配置文件讀寫這里就不詳細介紹了,主要的配置文件格式如下
[reactor]
ip = 127.0.0.1
port = 7777
maxConn = 1024
threadNum = 5
? 一個主題衫冻,下面很多key-value的鍵值對.
代碼如下厕怜。
11.1 功能實現(xiàn)
lars_reactor/include/config_file.h
#pragma once
#include <string>
#include <vector>
#include <map>
//定義一個存放配置信息的map
//key 是string 存放一個標題section
//value 是一個map 存放該標題下面的所有key-value鍵值對
typedef std::map<std::string, std::map<std::string, std::string> *> STR_MAP;
typedef STR_MAP::iterator STR_MAP_ITER;
//設計成單例模式
class config_file {
public:
~config_file();
//獲取字符串類型配置信息
std::string GetString(const std::string& section, const std::string& key, const std::string& default_value = "");
//字符串集合配置信息
std::vector<std::string> GetStringList(const std::string& section, const std::string& key);
//獲取整型類型配置信息
unsigned GetNumber(const std::string& section, const std::string& key, unsigned default_value = 0);
//獲取布爾類型配置信息
bool GetBool(const std::string& section, const std::string& key, bool default_value = false);
//獲取浮點類型配置信息
float GetFloat(const std::string& section, const std::string& key, const float& default_value);
//設置配置文件所在路徑
static bool setPath(const std::string& path);
//獲取單例
static config_file *instance();
private:
config_file() { } //構造私有
//字符串配置文件解析基礎方法
bool isSection(std::string line, std::string& section);
unsigned parseNumber(const std::string& s);
std::string trimLeft(const std::string& s);
std::string trimRight(const std::string& s);
std::string trim(const std::string& s);
bool Load(const std::string& path);
static config_file *config;//唯一讀取配置文件實例
STR_MAP _map;
};
lars_reactor/src/config_file.cpp
#include "config_file.h"
#include <map>
#include <fstream>
#include <iostream>
#include <sstream>
#include <assert.h>
#include <strings.h>
config_file* config_file::config = NULL;
config_file::~config_file()
{
for (STR_MAP_ITER it = _map.begin(); it != _map.end(); ++it)
{
delete it->second;
}
}
//獲取字符串類型鍵值對
std::string config_file::GetString(const std::string& section, const std::string& key, const std::string& default_value)
{
STR_MAP_ITER it = _map.find(section);
if (it != _map.end())
{
std::map<std::string, std::string>::const_iterator it1 = it->second->find(key);
if (it1 != it->second->end())
{
return it1->second;
}
}
return default_value;
}
//獲取浮點類型鍵值對
float config_file::GetFloat(const std::string& section, const std::string& key, const float& default_value)
{
std::ostringstream convert1;
convert1 << default_value;
//將浮點轉換成字符串甚疟,然后按照字符串業(yè)務處理
std::string default_value_str = convert1.str();
std::string text = GetString(section, key, default_value_str);
std::istringstream convert2(text);
float fresult;
if (!(convert2 >> fresult)) //如果Result放不下text對應的數(shù)字,執(zhí)行將返回0;
fresult = 0;
return fresult;
}
//價值配置文件
bool config_file::Load(const std::string& path)
{
std::ifstream ifs(path.c_str());
if (!ifs.good())
{
return false;
}
std::string line;
std::map<std::string, std::string> *m = NULL;
while (!ifs.eof() && ifs.good())
{
getline(ifs, line);
std::string section;
if (isSection(line, section))
{
STR_MAP_ITER it = _map.find(section);
if (it == _map.end())
{
m = new std::map<std::string, std::string>();
_map.insert(STR_MAP::value_type(section, m));
}
else
{
m = it->second;
}
continue;
}
size_t equ_pos = line.find('=');
if (equ_pos == std::string::npos)
{
continue;
}
std::string key = line.substr(0, equ_pos);
std::string value = line.substr(equ_pos + 1);
key = trim(key);
value = trim(value);
if (key.empty())
{
continue;
}
if (key[0] == '#' || key[0] == ';') // skip comment
{
continue;
}
std::map<std::string, std::string>::iterator it1 = m->find(key);
if (it1 != m->end())
{
it1->second = value;
}
else
{
m->insert(std::map<std::string, std::string>::value_type(key, value));
}
}
ifs.close();
return true;
}
std::vector<std::string> config_file::GetStringList(const std::string& section, const std::string& key)
{
std::vector<std::string> v;
std::string str = GetString(section, key, "");
std::string sep = ", \t";
std::string substr;
std::string::size_type start = 0;
std::string::size_type index;
while ((index = str.find_first_of(sep, start)) != std::string::npos)
{
substr = str.substr(start, index - start);
v.push_back(substr);
start = str.find_first_not_of(sep, index);
if (start == std::string::npos)
{
return v;
}
}
substr = str.substr(start);
v.push_back(substr);
return v;
}
//獲取整型類型鍵值對
unsigned config_file::GetNumber(const std::string& section, const std::string& key, unsigned default_value)
{
STR_MAP_ITER it = _map.find(section);
if (it != _map.end())
{
std::map<std::string, std::string>::const_iterator it1 = it->second->find(key);
if (it1 != it->second->end())
{
return parseNumber(it1->second);
}
}
return default_value;
}
//獲取布爾類型鍵值對
bool config_file::GetBool(const std::string& section, const std::string& key, bool default_value)
{
STR_MAP_ITER it = _map.find(section);
if (it != _map.end())
{
std::map<std::string, std::string>::const_iterator it1 = it->second->find(key);
if (it1 != it->second->end())
{
if (strcasecmp(it1->second.c_str(), "true") == 0)
{
return true;
}
}
}
return default_value;
}
bool config_file::isSection(std::string line, std::string& section)
{
section = trim(line);
if (section.empty() || section.length() <= 2)
{
return false;
}
if (section.at(0) != '[' || section.at(section.length() - 1) != ']')
{
return false;
}
section = section.substr(1, section.length() - 2);
section = trim(section);
return true;
}
unsigned config_file::parseNumber(const std::string& s)
{
std::istringstream iss(s);
long long v = 0;
iss >> v;
return v;
}
std::string config_file::trimLeft(const std::string& s)
{
size_t first_not_empty = 0;
std::string::const_iterator beg = s.begin();
while (beg != s.end())
{
if (!isspace(*beg))
{
break;
}
first_not_empty++;
beg++;
}
return s.substr(first_not_empty);
}
std::string config_file::trimRight(const std::string& s)
{
size_t last_not_empty = s.length();
std::string::const_iterator end = s.end();
while (end != s.begin())
{
end--;
if (!isspace(*end))
{
break;
}
last_not_empty--;
}
return s.substr(0, last_not_empty);
}
std::string config_file::trim(const std::string& s)
{
return trimLeft(trimRight(s));
}
config_file *config_file::instance()
{
assert(config != NULL);
return config;
}
//設置配置文件所在路徑
bool config_file::setPath(const std::string& path)
{
assert(config == NULL);
//創(chuàng)建對象
config = new config_file();
//加載文件
return config->Load(path);
}
11.2 完成Lars Reactor V0.9開發(fā)
serv.conf
[reactor]
ip = 127.0.0.1
port = 7777
maxConn = 1024
threadNum = 5
server.cpp
#include "tcp_server.h"
#include <string>
#include <string.h>
#include "config_file.h"
//回顯業(yè)務的回調(diào)函數(shù)
void callback_busi(const char *data, uint32_t len, int msgid, net_connection *conn, void *user_data)
{
printf("callback_busi ...\n");
//直接回顯
conn->send_message(data, len, msgid);
}
//打印信息回調(diào)函數(shù)
void print_busi(const char *data, uint32_t len, int msgid, net_connection *conn, void *user_data)
{
printf("recv client: [%s]\n", data);
printf("msgid: [%d]\n", msgid);
printf("len: [%d]\n", len);
}
//新客戶端創(chuàng)建的回調(diào)
void on_client_build(net_connection *conn, void *args)
{
int msgid = 101;
const char *msg = "welcome! you online..";
conn->send_message(msg, strlen(msg), msgid);
}
//客戶端銷毀的回調(diào)
void on_client_lost(net_connection *conn, void *args)
{
printf("connection is lost !\n");
}
int main()
{
event_loop loop;
//加載配置文件
config_file::setPath("./serv.conf");
std::string ip = config_file::instance()->GetString("reactor", "ip", "0.0.0.0");
short port = config_file::instance()->GetNumber("reactor", "port", 8888);
printf("ip = %s, port = %d\n", ip.c_str(), port);
tcp_server server(&loop, ip.c_str(), port);
//注冊消息業(yè)務路由
server.add_msg_router(1, callback_busi);
server.add_msg_router(2, print_busi);
//注冊鏈接hook回調(diào)
server.set_conn_start(on_client_build);
server.set_conn_close(on_client_lost);
loop.event_process();
return 0;
}
關于作者:
作者:Aceld(劉丹冰)
mail: danbing.at@gmail.com
github: https://github.com/aceld
原創(chuàng)書籍gitbook: http://legacy.gitbook.com/@aceld
原創(chuàng)聲明:未經(jīng)作者允許請勿轉載, 如果轉載請注明出處