配置文件读写这里就不详细介绍了,主要的配置文件格式如下

  1. [reactor]
  2. ip = 127.0.0.1
  3. port = 7777
  4. maxConn = 1024
  5. threadNum = 5
  1. 一个主题,下面很多key-value的键值对.

代码如下。

11.1 功能实现

lars_reactor/include/config_file.h

  1. #pragma once
  2. #include <string>
  3. #include <vector>
  4. #include <map>
  5. //定义一个存放配置信息的map
  6. //key 是string 存放一个标题section
  7. //value 是一个map 存放该标题下面的所有key-value键值对
  8. typedef std::map<std::string, std::map<std::string, std::string> *> STR_MAP;
  9. typedef STR_MAP::iterator STR_MAP_ITER;
  10. //设计成单例模式
  11. class config_file {
  12. public:
  13. ~config_file();
  14. //获取字符串类型配置信息
  15. std::string GetString(const std::string& section, const std::string& key, const std::string& default_value = "");
  16. //字符串集合配置信息
  17. std::vector<std::string> GetStringList(const std::string& section, const std::string& key);
  18. //获取整型类型配置信息
  19. unsigned GetNumber(const std::string& section, const std::string& key, unsigned default_value = 0);
  20. //获取布尔类型配置信息
  21. bool GetBool(const std::string& section, const std::string& key, bool default_value = false);
  22. //获取浮点类型配置信息
  23. float GetFloat(const std::string& section, const std::string& key, const float& default_value);
  24. //设置配置文件所在路径
  25. static bool setPath(const std::string& path);
  26. //获取单例
  27. static config_file *instance();
  28. private:
  29. config_file() { } //构造私有
  30. //字符串配置文件解析基础方法
  31. bool isSection(std::string line, std::string& section);
  32. unsigned parseNumber(const std::string& s);
  33. std::string trimLeft(const std::string& s);
  34. std::string trimRight(const std::string& s);
  35. std::string trim(const std::string& s);
  36. bool Load(const std::string& path);
  37. static config_file *config;//唯一读取配置文件实例
  38. STR_MAP _map;
  39. };

lars_reactor/src/config_file.cpp

  1. #include "config_file.h"
  2. #include <map>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <sstream>
  6. #include <assert.h>
  7. #include <strings.h>
  8. config_file* config_file::config = NULL;
  9. config_file::~config_file()
  10. {
  11. for (STR_MAP_ITER it = _map.begin(); it != _map.end(); ++it)
  12. {
  13. delete it->second;
  14. }
  15. }
  16. //获取字符串类型键值对
  17. std::string config_file::GetString(const std::string& section, const std::string& key, const std::string& default_value)
  18. {
  19. STR_MAP_ITER it = _map.find(section);
  20. if (it != _map.end())
  21. {
  22. std::map<std::string, std::string>::const_iterator it1 = it->second->find(key);
  23. if (it1 != it->second->end())
  24. {
  25. return it1->second;
  26. }
  27. }
  28. return default_value;
  29. }
  30. //获取浮点类型键值对
  31. float config_file::GetFloat(const std::string& section, const std::string& key, const float& default_value)
  32. {
  33. std::ostringstream convert1;
  34. convert1 << default_value;
  35. //将浮点转换成字符串,然后按照字符串业务处理
  36. std::string default_value_str = convert1.str();
  37. std::string text = GetString(section, key, default_value_str);
  38. std::istringstream convert2(text);
  39. float fresult;
  40. if (!(convert2 >> fresult)) //如果Result放不下text对应的数字,执行将返回0;
  41. fresult = 0;
  42. return fresult;
  43. }
  44. //价值配置文件
  45. bool config_file::Load(const std::string& path)
  46. {
  47. std::ifstream ifs(path.c_str());
  48. if (!ifs.good())
  49. {
  50. return false;
  51. }
  52. std::string line;
  53. std::map<std::string, std::string> *m = NULL;
  54. while (!ifs.eof() && ifs.good())
  55. {
  56. getline(ifs, line);
  57. std::string section;
  58. if (isSection(line, section))
  59. {
  60. STR_MAP_ITER it = _map.find(section);
  61. if (it == _map.end())
  62. {
  63. m = new std::map<std::string, std::string>();
  64. _map.insert(STR_MAP::value_type(section, m));
  65. }
  66. else
  67. {
  68. m = it->second;
  69. }
  70. continue;
  71. }
  72. size_t equ_pos = line.find('=');
  73. if (equ_pos == std::string::npos)
  74. {
  75. continue;
  76. }
  77. std::string key = line.substr(0, equ_pos);
  78. std::string value = line.substr(equ_pos + 1);
  79. key = trim(key);
  80. value = trim(value);
  81. if (key.empty())
  82. {
  83. continue;
  84. }
  85. if (key[0] == '#' || key[0] == ';') // skip comment
  86. {
  87. continue;
  88. }
  89. std::map<std::string, std::string>::iterator it1 = m->find(key);
  90. if (it1 != m->end())
  91. {
  92. it1->second = value;
  93. }
  94. else
  95. {
  96. m->insert(std::map<std::string, std::string>::value_type(key, value));
  97. }
  98. }
  99. ifs.close();
  100. return true;
  101. }
  102. std::vector<std::string> config_file::GetStringList(const std::string& section, const std::string& key)
  103. {
  104. std::vector<std::string> v;
  105. std::string str = GetString(section, key, "");
  106. std::string sep = ", \t";
  107. std::string substr;
  108. std::string::size_type start = 0;
  109. std::string::size_type index;
  110. while ((index = str.find_first_of(sep, start)) != std::string::npos)
  111. {
  112. substr = str.substr(start, index - start);
  113. v.push_back(substr);
  114. start = str.find_first_not_of(sep, index);
  115. if (start == std::string::npos)
  116. {
  117. return v;
  118. }
  119. }
  120. substr = str.substr(start);
  121. v.push_back(substr);
  122. return v;
  123. }
  124. //获取整型类型键值对
  125. unsigned config_file::GetNumber(const std::string& section, const std::string& key, unsigned default_value)
  126. {
  127. STR_MAP_ITER it = _map.find(section);
  128. if (it != _map.end())
  129. {
  130. std::map<std::string, std::string>::const_iterator it1 = it->second->find(key);
  131. if (it1 != it->second->end())
  132. {
  133. return parseNumber(it1->second);
  134. }
  135. }
  136. return default_value;
  137. }
  138. //获取布尔类型键值对
  139. bool config_file::GetBool(const std::string& section, const std::string& key, bool default_value)
  140. {
  141. STR_MAP_ITER it = _map.find(section);
  142. if (it != _map.end())
  143. {
  144. std::map<std::string, std::string>::const_iterator it1 = it->second->find(key);
  145. if (it1 != it->second->end())
  146. {
  147. if (strcasecmp(it1->second.c_str(), "true") == 0)
  148. {
  149. return true;
  150. }
  151. }
  152. }
  153. return default_value;
  154. }
  155. bool config_file::isSection(std::string line, std::string& section)
  156. {
  157. section = trim(line);
  158. if (section.empty() || section.length() <= 2)
  159. {
  160. return false;
  161. }
  162. if (section.at(0) != '[' || section.at(section.length() - 1) != ']')
  163. {
  164. return false;
  165. }
  166. section = section.substr(1, section.length() - 2);
  167. section = trim(section);
  168. return true;
  169. }
  170. unsigned config_file::parseNumber(const std::string& s)
  171. {
  172. std::istringstream iss(s);
  173. long long v = 0;
  174. iss >> v;
  175. return v;
  176. }
  177. std::string config_file::trimLeft(const std::string& s)
  178. {
  179. size_t first_not_empty = 0;
  180. std::string::const_iterator beg = s.begin();
  181. while (beg != s.end())
  182. {
  183. if (!isspace(*beg))
  184. {
  185. break;
  186. }
  187. first_not_empty++;
  188. beg++;
  189. }
  190. return s.substr(first_not_empty);
  191. }
  192. std::string config_file::trimRight(const std::string& s)
  193. {
  194. size_t last_not_empty = s.length();
  195. std::string::const_iterator end = s.end();
  196. while (end != s.begin())
  197. {
  198. end--;
  199. if (!isspace(*end))
  200. {
  201. break;
  202. }
  203. last_not_empty--;
  204. }
  205. return s.substr(0, last_not_empty);
  206. }
  207. std::string config_file::trim(const std::string& s)
  208. {
  209. return trimLeft(trimRight(s));
  210. }
  211. config_file *config_file::instance()
  212. {
  213. assert(config != NULL);
  214. return config;
  215. }
  216. //设置配置文件所在路径
  217. bool config_file::setPath(const std::string& path)
  218. {
  219. assert(config == NULL);
  220. //创建对象
  221. config = new config_file();
  222. //加载文件
  223. return config->Load(path);
  224. }

11.2 完成Lars Reactor V0.9开发

serv.conf

  1. [reactor]
  2. ip = 127.0.0.1
  3. port = 7777
  4. maxConn = 1024
  5. threadNum = 5

server.cpp

  1. #include "tcp_server.h"
  2. #include <string>
  3. #include <string.h>
  4. #include "config_file.h"
  5. //回显业务的回调函数
  6. void callback_busi(const char *data, uint32_t len, int msgid, net_connection *conn, void *user_data)
  7. {
  8. printf("callback_busi ...\n");
  9. //直接回显
  10. conn->send_message(data, len, msgid);
  11. }
  12. //打印信息回调函数
  13. void print_busi(const char *data, uint32_t len, int msgid, net_connection *conn, void *user_data)
  14. {
  15. printf("recv client: [%s]\n", data);
  16. printf("msgid: [%d]\n", msgid);
  17. printf("len: [%d]\n", len);
  18. }
  19. //新客户端创建的回调
  20. void on_client_build(net_connection *conn, void *args)
  21. {
  22. int msgid = 101;
  23. const char *msg = "welcome! you online..";
  24. conn->send_message(msg, strlen(msg), msgid);
  25. }
  26. //客户端销毁的回调
  27. void on_client_lost(net_connection *conn, void *args)
  28. {
  29. printf("connection is lost !\n");
  30. }
  31. int main()
  32. {
  33. event_loop loop;
  34. //加载配置文件
  35. config_file::setPath("./serv.conf");
  36. std::string ip = config_file::instance()->GetString("reactor", "ip", "0.0.0.0");
  37. short port = config_file::instance()->GetNumber("reactor", "port", 8888);
  38. printf("ip = %s, port = %d\n", ip.c_str(), port);
  39. tcp_server server(&loop, ip.c_str(), port);
  40. //注册消息业务路由
  41. server.add_msg_router(1, callback_busi);
  42. server.add_msg_router(2, print_busi);
  43. //注册链接hook回调
  44. server.set_conn_start(on_client_build);
  45. server.set_conn_close(on_client_lost);
  46. loop.event_process();
  47. return 0;
  48. }