(12)配置文件讀寫功能(Reactor部分)-【Lars-基于C++負載均衡遠程服務器調(diào)度系統(tǒng)教程】

【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)作者允許請勿轉載, 如果轉載請注明出處

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哩至,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蜜自,更是在濱河造成了極大的恐慌菩貌,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,222評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件重荠,死亡現(xiàn)場離奇詭異箭阶,居然都是意外死亡,警方通過查閱死者的電腦和手機戈鲁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評論 3 385
  • 文/潘曉璐 我一進店門仇参,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人婆殿,你說我怎么就攤上這事诈乒。” “怎么了鸣皂?”我有些...
    開封第一講書人閱讀 157,720評論 0 348
  • 文/不壞的土叔 我叫張陵抓谴,是天一觀的道長。 經(jīng)常有香客問我寞缝,道長癌压,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,568評論 1 284
  • 正文 為了忘掉前任荆陆,我火速辦了婚禮滩届,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己帜消,他們只是感情好棠枉,可當我...
    茶點故事閱讀 65,696評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著泡挺,像睡著了一般辈讶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上娄猫,一...
    開封第一講書人閱讀 49,879評論 1 290
  • 那天贱除,我揣著相機與錄音,去河邊找鬼媳溺。 笑死月幌,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的悬蔽。 我是一名探鬼主播扯躺,決...
    沈念sama閱讀 39,028評論 3 409
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蝎困!你這毒婦竟也來了录语?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,773評論 0 268
  • 序言:老撾萬榮一對情侶失蹤难衰,失蹤者是張志新(化名)和其女友劉穎钦无,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盖袭,經(jīng)...
    沈念sama閱讀 44,220評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡失暂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,550評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鳄虱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弟塞。...
    茶點故事閱讀 38,697評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖拙已,靈堂內(nèi)的尸體忽然破棺而出决记,到底是詐尸還是另有隱情,我是刑警寧澤倍踪,帶...
    沈念sama閱讀 34,360評論 4 332
  • 正文 年R本政府宣布系宫,位于F島的核電站,受9級特大地震影響建车,放射性物質發(fā)生泄漏扩借。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,002評論 3 315
  • 文/蒙蒙 一缤至、第九天 我趴在偏房一處隱蔽的房頂上張望潮罪。 院中可真熱鬧,春花似錦、人聲如沸嫉到。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,782評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽何恶。三九已至孽锥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間细层,已是汗流浹背忱叭。 一陣腳步聲響...
    開封第一講書人閱讀 32,010評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留今艺,地道東北人。 一個月前我還...
    沈念sama閱讀 46,433評論 2 360
  • 正文 我出身青樓爵卒,卻偏偏與公主長得像虚缎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子钓株,可洞房花燭夜當晚...
    茶點故事閱讀 43,587評論 2 350

推薦閱讀更多精彩內(nèi)容