client_factory.hpp文件源码
#pragma once
#include "simple_client.hpp"
namespace cinatra {
class client_factory {
public:
static client_factory& instance() {
static client_factory instance;
return instance;
}
template<typename...Args>
auto new_client(Args&&... args) {
return std::make_shared<simple_client>(ios_, std::forward<Args>(args)...);
}
void run() {
ios_.run();
}
void stop() {
ios_.stop();
}
private:
client_factory() : work_(ios_) {
thd_ = std::make_shared<std::thread>([this] {ios_.run(); });
}
~client_factory() {
ios_.stop();
thd_->join();
}
client_factory(const client_factory&) = delete;
client_factory& operator=(const client_factory&) = delete;
client_factory(client_factory&&) = delete;
client_factory& operator=(client_factory&&) = delete;
boost::asio::io_service ios_;
boost::asio::io_service::work work_;
std::shared_ptr<std::thread> thd_;
};
#ifdef CINATRA_ENABLE_SSL
template<res_content_type CONTENT_TYPE = res_content_type::json, size_t TIMEOUT = 3000, http_method METHOD = POST>
inline std::string send_msg(std::string ip, std::string api, std::string msg, boost::asio::ssl::context & context) {
assert(!api.empty() && api[0] == '/');
auto client = client_factory::instance().new_client(std::move(ip), "https", context);
return client->send_msg<CONTENT_TYPE>(std::move(api), std::move(msg));
}
template<res_content_type CONTENT_TYPE = res_content_type::json, size_t TIMEOUT = 3000, http_method METHOD = POST>
inline std::string send_msg(std::string ip, std::string port, std::string api, std::string msg, boost::asio::ssl::context & context) {
assert(!api.empty() && api[0] == '/');
auto client = client_factory::instance().new_client(std::move(ip), std::move(port), context);
return client->send_msg<CONTENT_TYPE>(std::move(api), std::move(msg));
}
#else
template<res_content_type CONTENT_TYPE = res_content_type::json, size_t TIMEOUT = 3000, http_method METHOD = POST>
inline std::string send_msg(std::string ip, std::string api, std::string msg) {
assert(!api.empty() && api[0] == '/');
auto client = client_factory::instance().new_client(std::move(ip), "http");
return client->send_msg<CONTENT_TYPE>(std::move(api), std::move(msg));
}
template<res_content_type CONTENT_TYPE = res_content_type::json, size_t TIMEOUT = 3000, http_method METHOD = POST>
inline std::string send_msg(std::string ip, std::string port, std::string api, std::string msg) {
assert(!api.empty() && api[0] == '/');
auto client = client_factory::instance().new_client(std::move(ip), std::move(port));
return client->send_msg<CONTENT_TYPE>(std::move(api), std::move(msg));
}
#endif
}
C++语法学习:
- 命名空间cinatra下定义了一个类client_factory
- template<typename…Args>是C++11开始有的语法,被其修饰的方法表示可以接受零个或者更多参数。
- std::make_shared的函数声明如下:
该函数用来对类型为T的对象分配一片空间并将其封装成类对象,args是传递给该待被构造的对象的构造函数的形参,最终结果返回一个shared_ptr类对象,该类内部保存一直指针指向刚才传进来的内存空间,该类对象内部引用计数值为1。template <class T, class... Args> shared_ptr<T> make_shared (Args&&... args);
如以下源码所示:
new_client()函数返回了一个包含simple_client对象地址的shared_ptr<simple_client>对象。/* * 创建客户端对象 */ template<typename...Args> auto new_client(Args&&... args) { return std::make_shared<simple_client>(ios_, std::forward<Args>(args)...); }
- delete关键字用来指定某个函数程序员不能显示调用
- #ifdef CINATRA_ENABLE_SSL #else #endif 是条件编译语句:表示如果之前已经定义过CINATRA_ENABLE_SSL字段则编译“#ifdef CINATRA_ENABLE_SSL #else”之间的代码,否则编译“ #else #endif”之间的代码
源码学习:
cinatra::client_factory类图如下所示:
Boost.Asio是一个跨平台的C++库,该库主要用在网络和低层次的IO编程方面进行使用,该库作用是通过使用现代C++方法对外提供一致的异步通信模型。
关于boost::asio::io_service类介绍如下:
```cpp
namespace boost {
namespace asio {
#if !defined(BOOST_ASIO_NO_DEPRECATED)
/// Typedef for backwards compatibility.
typedef io_context io_service;
#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
} // namespace asio
} // namespace boost
```
io_context的作用是为想要使用异步IO对象的用户提供核心的IO函数接口,包括:
- boost::asio::ip::tcp::socket
- boost::asio::ip::tcp::acceptor
- boost::asio::ip::udp::socket
- deadline_timer
该类也提供开发者用来自定义实现异步service的接口。
关于io_context的更多介绍详见:io_context介绍
关于boost::asio::io_context::work类介绍如下:
如上所示:该类主要用来告知io_context类work什么时候开始和结束。当work正在运行的时候确保io_context对象的run()方法不会退出,并且当所有的work都结束的时候才使run()退出执行。
关于std::shared_ptr<std::thread>的相关介绍:
C++11之后引入的线程库,此处主要将其封装在shared_ptr对象中进行管理。
io_context中两个关键函数:
io_context::run(); //Run the io_context object's event processing loop
io_context::stop();//Stop the io_context object's event processing loop.
std::shared_ptr<std::thread> thd_:管理线程对象
创建client_factory的时候就通过ios_对象创建了线程对象,并封装到shared_ptr对象中以初始化thd_成员变量,同时启动ios_对象的事件处理循环机制。
在对client_factory对象进行析构(空间回收)的时候结束ios_对象的事件处理循环机制,同时调用thd_的join()方法,join()方法的介绍如下所示:
如图中所示:
1.该方法当线程中所有的执行操作都执行完成的时候会向上(其调用者)返回。
2.当当前线程中的所有操作执行完成并向上(当前线程的调用者)返回时会同步状态信息,同时会对其调用者的执行进行block(锁住、阻塞)直到当前线程执行结束并向上返回时。
3.调用该函数后,线程对象会变成一个non-joinable的对象,之后就可以安全的销毁。
client_factory发送消息
- 通过CINATRA_ENABLE_SSL的定义来决定是使用“HTTP”还是“HTTPS”的方式进行消息的发送。
- 不管以“HTTP”还是“HTTPS”的方式都定义两个方法send_msg,第一个方法通过ip来构造客户端对象,发送api和msg;第二个方法通过ip和port来构造客户端对象,发送api和msg。
以上即为我对client_factory.hpp的学习结果,总结的有些混乱。