boost asio 实现一个TCP服务端线程池

1 篇文章 0 订阅
1 篇文章 0 订阅

tcp的服务器端绑定并监听端口,如果客户端比较少,可以对每个客户端创建一个线程进行通讯处理,但当客户端的数量比较庞大的时候这种思路就变得不可行,一方面线程切换的开销太大,另一方面,多数线程并不出于“工作”状态,长期出于等待事件的状态。这时,可以使用线程池的架构加快处理速度。

废话少说,直接上代码


  1. #include <stdio.h>
  2. #include <cstdlib>
  3. #include <iostream>
  4. #include <boost/thread.hpp>
  5. #include <boost/aligned_storage.hpp>
  6. #include <boost/array.hpp>
  7. #include <boost/bind.hpp>
  8. #include <boost/enable_shared_from_this.hpp>
  9. #include <boost/noncopyable.hpp>
  10. #include <boost/shared_ptr.hpp>
  11. #include <boost/asio.hpp>
  12. using boost::asio::ip::tcp;
  13. class handler_allocator
  14. : private boost::noncopyable
  15. {
  16. public:
  17. handler_allocator()
  18. : in_use_( false)
  19. {
  20. }
  21. void* allocate(std::size_t size)
  22. {
  23. if (!in_use_ && size < storage_.size)
  24. {
  25. in_use_ = true;
  26. return storage_.address();
  27. }
  28. else
  29. {
  30. return :: operator new(size);
  31. }
  32. }
  33. void deallocate(void* pointer)
  34. {
  35. if (pointer == storage_.address())
  36. {
  37. in_use_ = false;
  38. }
  39. else
  40. {
  41. :: operator delete(pointer);
  42. }
  43. }
  44. private:
  45. // Storage space used for handler-based custom memory allocation.
  46. boost::aligned_storage< 1024> storage_;
  47. // Whether the handler-based custom allocation storage has been used.
  48. bool in_use_;
  49. };
  50. template < typename Handler>
  51. class custom_alloc_handler
  52. {
  53. public:
  54. custom_alloc_handler(handler_allocator& a, Handler h)
  55. : allocator_(a),
  56. handler_(h)
  57. {
  58. }
  59. template < typename Arg1>
  60. void operator()(Arg1 arg1)
  61. {
  62. handler_(arg1);
  63. }
  64. template < typename Arg1, typename Arg2>
  65. void operator()(Arg1 arg1, Arg2 arg2)
  66. {
  67. handler_(arg1, arg2);
  68. }
  69. friend void* asio_handler_allocate(std::size_t size,
  70. custom_alloc_handler<Handler>* this_handler)
  71. {
  72. return this_handler->allocator_.allocate(size);
  73. }
  74. friend void asio_handler_deallocate(void* pointer, std::size_t /*size*/,
  75. custom_alloc_handler<Handler>* this_handler)
  76. {
  77. this_handler->allocator_.deallocate(pointer);
  78. }
  79. private:
  80. handler_allocator& allocator_;
  81. Handler handler_;
  82. };
  83. // Helper function to wrap a handler object to add custom allocation.
  84. template < typename Handler>
  85. inline custom_alloc_handler<Handler> make_custom_alloc_handler(
  86. handler_allocator& a, Handler h)
  87. {
  88. return custom_alloc_handler<Handler>(a, h);
  89. }
  90. /// A pool of io_service objects.
  91. class io_service_pool
  92. : private boost::noncopyable
  93. {
  94. public:
  95. /// Construct the io_service pool.
  96. explicit io_service_pool(std::size_t pool_size) : next_io_service_(0)
  97. {
  98. if (pool_size == 0)
  99. throw std::runtime_error( "io_service_pool size is 0");
  100. // Give all the io_services work to do so that their run() functions will not
  101. // exit until they are explicitly stopped.
  102. for ( std:: size_t i = 0; i < pool_size; ++i)
  103. {
  104. io_service_ptr io_service(new boost::asio::io_service);
  105. work_ptr work(new boost::asio::io_service::work(*io_service));
  106. io_services_.push_back(io_service);
  107. work_.push_back(work);
  108. }
  109. }
  110. // Run all io_service objects in the pool.
  111. void run()
  112. {
  113. // Create a pool of threads to run all of the io_services.
  114. std:: vector<boost:: shared_ptr<boost::thread> > threads;
  115. for ( std:: size_t i = 0; i < io_services_.size(); ++i)
  116. {
  117. boost:: shared_ptr<boost::thread> thread( new boost::thread(
  118. boost::bind(&boost::asio::io_service::run, io_services_[i])));
  119. threads.push_back(thread);
  120. }
  121. // Wait for all threads in the pool to exit.
  122. for ( std:: size_t i = 0; i < threads.size(); ++i)
  123. threads[i]->join();
  124. }
  125. // Stop all io_service objects in the pool.
  126. void stop()
  127. {
  128. // Explicitly stop all io_services.
  129. for ( std:: size_t i = 0; i < io_services_.size(); ++i)
  130. io_services_[i]->stop();
  131. }
  132. // Get an io_service to use.
  133. boost::asio:: io_service& get_io_service()
  134. {
  135. // Use a round-robin scheme to choose the next io_service to use.
  136. boost::asio::io_service& io_service = *io_services_[next_io_service_];
  137. ++next_io_service_;
  138. if (next_io_service_ == io_services_.size())
  139. next_io_service_ = 0;
  140. return io_service;
  141. }
  142. private:
  143. typedef boost:: shared_ptr<boost::asio::io_service> io_service_ptr;
  144. typedef boost:: shared_ptr<boost::asio::io_service::work> work_ptr;
  145. /// The pool of io_services.
  146. std:: vector<io_service_ptr> io_services_;
  147. /// The work that keeps the io_services running.
  148. std:: vector<work_ptr> work_;
  149. /// The next io_service to use for a connection.
  150. std:: size_t next_io_service_;
  151. };
  152. class session
  153. : public boost::enable_shared_from_this<session>
  154. {
  155. public:
  156. session(boost::asio::io_service& work_service
  157. , boost::asio::io_service& io_service)
  158. : socket_(io_service)
  159. , io_work_service(work_service)
  160. {
  161. }
  162. tcp:: socket& socket()
  163. {
  164. return socket_;
  165. }
  166. void start()
  167. {
  168. boost::system::error_code error;
  169. handle_write(error);
  170. socket_.async_read_some(boost::asio::buffer(data_),
  171. make_custom_alloc_handler(allocator_,
  172. boost::bind(&session::handle_read,
  173. shared_from_this(),
  174. boost::asio::placeholders::error,
  175. boost::asio::placeholders::bytes_transferred)));
  176. }
  177. void handle_read(const boost::system::error_code& error,
  178. size_t bytes_transferred)
  179. {
  180. if (!error)
  181. {
  182. boost:: shared_ptr< std:: vector< char> > buf( new std:: vector< char>);
  183. buf->resize(bytes_transferred);
  184. std::copy(data_.begin(), data_.begin() + bytes_transferred, buf->begin());
  185. io_work_service.post(boost::bind(&session::on_receive
  186. , shared_from_this(), buf, bytes_transferred));
  187. socket_.async_read_some(boost::asio::buffer(data_),
  188. make_custom_alloc_handler(allocator_,
  189. boost::bind(&session::handle_read,
  190. shared_from_this(),
  191. boost::asio::placeholders::error,
  192. boost::asio::placeholders::bytes_transferred)));
  193. }
  194. }
  195. void handle_write(const boost::system::error_code& error)
  196. {
  197. if (!error)
  198. {
  199. char notice[] = "Welcome to Connect to Hiper Service";
  200. size_t num;
  201. try
  202. {
  203. num = socket_.send(boost::asio::buffer(notice));
  204. }
  205. catch( std::exception &e)
  206. {
  207. std:: cout<< "exception: "<<e.what()<< std:: endl;
  208. }
  209. if(num> 0)
  210. {
  211. std:: cout<< "send : "<< notice << std:: endl;
  212. }
  213. }
  214. }
  215. void on_receive(boost::shared_ptr<std::vector<char> > buffers
  216. , size_t bytes_transferred)
  217. {
  218. char* data_stream = &(*buffers->begin());
  219. // in here finish the work.
  220. std:: cout << "receive :" << bytes_transferred << " bytes." <<
  221. "message :" << data_stream << std:: endl;
  222. boost::system::error_code error;
  223. handle_write(error);
  224. }
  225. private:
  226. // The io_service used to finish the work.
  227. boost::asio::io_service& io_work_service;
  228. // The socket used to communicate with the client.
  229. tcp::socket socket_;
  230. // Buffer used to store data received from the client.
  231. boost:: array< char, 1024> data_;
  232. // The allocator to use for handler-based custom memory allocation.
  233. handler_allocator allocator_;
  234. };
  235. typedef boost:: shared_ptr<session> session_ptr;
  236. class server
  237. {
  238. public:
  239. server( short port, std:: size_t io_service_pool_size)
  240. : io_service_pool_(io_service_pool_size)
  241. , io_service_work_pool_(io_service_pool_size)
  242. , acceptor_(io_service_pool_.get_io_service(), tcp::endpoint(tcp::v4(), port))
  243. {
  244. session_ptr new_session(new session(io_service_work_pool_.get_io_service()
  245. , io_service_pool_. get_io_service ()));
  246. acceptor_.async_accept(new_session->socket(),
  247. boost::bind(&server::handle_accept, this, new_session,
  248. boost::asio::placeholders::error));
  249. }
  250. void handle_accept(session_ptr new_session,
  251. const boost::system::error_code& error)
  252. {
  253. if (!error)
  254. {
  255. new_session->start();
  256. new_session.reset( new session(io_service_work_pool_.get_io_service()
  257. , io_service_pool_.get_io_service()));
  258. acceptor_.async_accept(new_session->socket(),
  259. boost::bind(&server::handle_accept, this, new_session,
  260. boost::asio::placeholders::error));
  261. }
  262. }
  263. void run()
  264. {
  265. io_thread_.reset( new boost::thread(boost::bind(&io_service_pool::run
  266. , &io_service_pool_)));
  267. work_thread_.reset( new boost::thread(boost::bind(&io_service_pool::run
  268. , &io_service_work_pool_)));
  269. }
  270. void stop()
  271. {
  272. io_service_pool_.stop();
  273. io_service_work_pool_.stop();
  274. io_thread_->join();
  275. work_thread_->join();
  276. }
  277. private:
  278. boost:: shared_ptr<boost::thread> io_thread_;
  279. boost:: shared_ptr<boost::thread> work_thread_;
  280. io_service_pool io_service_pool_;
  281. io_service_pool io_service_work_pool_;
  282. tcp::acceptor acceptor_;
  283. };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值