boost asio one client one thread
总结了一个简单的boost asio的tcp服务器端与客户端通信流程.模型是一个client对应一个线程。先做一个记录,后续再对此进行优化。
环境:VS2017 + Boost 1.67
server:
#include <stdio.h>
#include <cstdlib>
#include <iostream>
#include <boost/thread.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp> using boost::asio::ip::tcp; class handler_allocator
: private boost::noncopyable
{
public:
handler_allocator()
: in_use_(false)
{
} void* allocate(std::size_t size)
{
if (!in_use_ && size < storage_.size)
{
in_use_ = true;
return storage_.address();
}
else
{
return ::operator new(size);
}
} void deallocate(void* pointer)
{
if (pointer == storage_.address())
{
in_use_ = false;
}
else
{
::operator delete(pointer);
}
} private:
// Storage space used for handler-based custom memory allocation.
boost::aligned_storage<> storage_; // Whether the handler-based custom allocation storage has been used.
bool in_use_;
}; template <typename Handler>
class custom_alloc_handler
{
public:
custom_alloc_handler(handler_allocator& a, Handler h)
: allocator_(a),
handler_(h)
{
} template <typename Arg1>
void operator()(Arg1 arg1)
{
handler_(arg1);
} template <typename Arg1, typename Arg2>
void operator()(Arg1 arg1, Arg2 arg2)
{
handler_(arg1, arg2);
} friend void* asio_handler_allocate(std::size_t size,
custom_alloc_handler<Handler>* this_handler)
{
return this_handler->allocator_.allocate(size);
} friend void asio_handler_deallocate(void* pointer, std::size_t /*size*/,
custom_alloc_handler<Handler>* this_handler)
{
this_handler->allocator_.deallocate(pointer);
} private:
handler_allocator & allocator_;
Handler handler_;
}; // Helper function to wrap a handler object to add custom allocation.
template <typename Handler>
inline custom_alloc_handler<Handler> make_custom_alloc_handler(
handler_allocator& a, Handler h)
{
return custom_alloc_handler<Handler>(a, h);
} /// A pool of io_service objects.
class io_service_pool
: private boost::noncopyable
{
public:
/// Construct the io_service pool.
explicit io_service_pool(std::size_t pool_size) : next_io_service_()
{
if (pool_size == )
throw std::runtime_error("io_service_pool size is 0"); // Give all the io_services work to do so that their run() functions will not
// exit until they are explicitly stopped.
for (std::size_t i = ; i < pool_size; ++i)
{
io_service_ptr io_service(new boost::asio::io_service);
work_ptr work(new boost::asio::io_service::work(*io_service));
io_services_.push_back(io_service);
work_.push_back(work);
}
} // Run all io_service objects in the pool.
void run()
{
// Create a pool of threads to run all of the io_services.
std::vector<boost::shared_ptr<boost::thread> > threads;
for (std::size_t i = ; i < io_services_.size(); ++i)
{
boost::shared_ptr<boost::thread> thread(new boost::thread(
boost::bind(&boost::asio::io_service::run, io_services_[i])));
threads.push_back(thread);
} // Wait for all threads in the pool to exit.
for (std::size_t i = ; i < threads.size(); ++i)
threads[i]->join();
} // Stop all io_service objects in the pool.
void stop()
{
// Explicitly stop all io_services.
for (std::size_t i = ; i < io_services_.size(); ++i)
io_services_[i]->stop();
} // Get an io_service to use.
boost::asio::io_service& get_io_service()
{
// Use a round-robin scheme to choose the next io_service to use.
boost::asio::io_service& io_service = *io_services_[next_io_service_];
++next_io_service_;
if (next_io_service_ == io_services_.size())
next_io_service_ = ;
return io_service;
} private:
typedef boost::shared_ptr<boost::asio::io_service> io_service_ptr;
typedef boost::shared_ptr<boost::asio::io_service::work> work_ptr; /// The pool of io_services.
std::vector<io_service_ptr> io_services_; /// The work that keeps the io_services running.
std::vector<work_ptr> work_; /// The next io_service to use for a connection.
std::size_t next_io_service_;
}; class session
: public boost::enable_shared_from_this<session>
{
public:
session(boost::asio::io_service& work_service
, boost::asio::io_service& io_service)
: socket_(io_service)
, io_work_service(work_service)
{
} tcp::socket& socket()
{
return socket_;
} void start()
{ boost::system::error_code error;
handle_write(error); socket_.async_read_some(boost::asio::buffer(data_),
make_custom_alloc_handler(allocator_,
boost::bind(&session::handle_read,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)));
} void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
boost::shared_ptr<std::vector<char> > buf(new std::vector<char>); buf->resize(bytes_transferred);
std::copy(data_.begin(), data_.begin() + bytes_transferred, buf->begin());
io_work_service.post(boost::bind(&session::on_receive
, shared_from_this(), buf, bytes_transferred)); socket_.async_read_some(boost::asio::buffer(data_),
make_custom_alloc_handler(allocator_,
boost::bind(&session::handle_read,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)));
}
} void handle_write(const boost::system::error_code& error)
{
if (!error)
{
char notice[] = "Welcome to Connect to Hiper Service";
size_t num;
try
{
num = socket_.send(boost::asio::buffer(notice));
}
catch (std::exception &e)
{
std::cout << "exception: " << e.what() << std::endl;
}
if (num>)
{
std::cout << "send : " << notice << std::endl;
}
}
} void on_receive(boost::shared_ptr<std::vector<char> > buffers
, size_t bytes_transferred)
{
char* data_stream = &(*buffers->begin());
// in here finish the work.
std::cout << "receive :" << bytes_transferred << " bytes." <<
"message :" << data_stream << std::endl; boost::system::error_code error;
handle_write(error);
} private:
// The io_service used to finish the work.
boost::asio::io_service& io_work_service; // The socket used to communicate with the client.
tcp::socket socket_; // Buffer used to store data received from the client.
boost::array<char, > data_; // The allocator to use for handler-based custom memory allocation.
handler_allocator allocator_;
}; typedef boost::shared_ptr<session> session_ptr; class server
{
public:
server(short port, std::size_t io_service_pool_size)
: io_service_pool_(io_service_pool_size)
, io_service_work_pool_(io_service_pool_size)
, acceptor_(io_service_pool_.get_io_service(), tcp::endpoint(tcp::v4(), port))
{
session_ptr new_session(new session(io_service_work_pool_.get_io_service()
, io_service_pool_.get_io_service()));
acceptor_.async_accept(new_session->socket(),
boost::bind(&server::handle_accept, this, new_session,
boost::asio::placeholders::error));
} void handle_accept(session_ptr new_session,
const boost::system::error_code& error)
{
if (!error)
{
new_session->start();
new_session.reset(new session(io_service_work_pool_.get_io_service()
, io_service_pool_.get_io_service()));
acceptor_.async_accept(new_session->socket(),
boost::bind(&server::handle_accept, this, new_session,
boost::asio::placeholders::error));
}
} void run()
{
io_thread_.reset(new boost::thread(boost::bind(&io_service_pool::run
, &io_service_pool_)));
work_thread_.reset(new boost::thread(boost::bind(&io_service_pool::run
, &io_service_work_pool_)));
} void stop()
{
io_service_pool_.stop();
io_service_work_pool_.stop(); io_thread_->join();
work_thread_->join();
} private:
boost::shared_ptr<boost::thread> io_thread_;
boost::shared_ptr<boost::thread> work_thread_;
io_service_pool io_service_pool_;
io_service_pool io_service_work_pool_;
tcp::acceptor acceptor_;
}; int main() {
server svr(, );
svr.run(); while (true)
{
boost::this_thread::sleep(boost::posix_time::seconds());
} return ;
}
client:
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/asio/placeholders.hpp>
#include <boost/system/error_code.hpp>
#include <boost/bind/bind.hpp>
#include<boost/thread.hpp> using namespace boost::asio;
using namespace std; class client
{
typedef client this_type;
typedef ip::tcp::acceptor acceptor_type;
typedef ip::tcp::endpoint endpoint_type;
typedef ip::tcp::socket socket_type;
typedef ip::address address_type;
typedef boost::shared_ptr<socket_type> sock_ptr;
typedef vector<char> buffer_type; private:
io_service m_io;
buffer_type m_buf;
endpoint_type m_ep;
public:
client() : m_buf(, ), m_ep(address_type::from_string("127.0.0.1"), )
{
start();
} void run()
{
m_io.run();
} void start()
{
sock_ptr sock(new socket_type(m_io));
sock->async_connect(m_ep, boost::bind(&this_type::conn_handler, this, boost::asio::placeholders::error, sock));
} void conn_handler(const boost::system::error_code&ec, sock_ptr sock)
{
if (ec)
{
std::cout << ec.message() << std::endl;
return;
}
cout << "Receive from " << sock->remote_endpoint().address() << ": ";
cout << "Port:" << sock->remote_endpoint().port() << endl;
sock->async_read_some(buffer(m_buf), boost::bind(&client::read_handler, this, boost::asio::placeholders::error, sock));
} void read_handler(const boost::system::error_code&ec, sock_ptr sock)
{
if (ec)
{
return;
}
sock->async_read_some(buffer(m_buf), boost::bind(&client::read_handler, this, boost::asio::placeholders::error, sock));
cout << &m_buf[] << endl; boost::this_thread::sleep(boost::posix_time::milliseconds()); char pmsg[] = "client 6666"; sock->async_write_some(buffer(pmsg), boost::bind(&this_type::write_handler, this, boost::asio::placeholders::error));
} void write_handler(const boost::system::error_code& ec)
{
if (ec)
{
std::cout << ec.message() << std::endl;
return;
} std::cout << "send success!" << std::endl; }
}; int main()
{
try
{
cout << "Client start." << endl;
client cl;
cl.run();
}
catch (std::exception &e)
{
cout << e.what() << endl;
} while (true)
{
boost::this_thread::sleep(boost::posix_time::seconds());
} return ;
}
boost asio one client one thread的更多相关文章
- c++ boost asio库初学习
前些日子研究了一个c++的一个socket库,留下范例代码给以后自己参考. 同步server: // asio_server.cpp : コンソール アプリケーションのエントリ ポイントを定義します. ...
- Boost.Asio基础(五) 异步编程初探
异步编程 本节深入讨论异步编程将遇到的若干问题.建议多次阅读,以便吃透这一节的内容,这一节是对整个boost.asio来说是非常重要的. 为什么须要异步 如前所述,通常同步编程要比异步编程更简单.同步 ...
- Boost.Asio 网络编程([译]Boost.Asio基本原理)
转自:https://m.w3cschool.cn/nlzbw/nlzbw-3vs825ya.html Boost.Asio基本原理 这一章涵盖了使用Boost.Asio时必须知道的一些事情.我们也将 ...
- Boost.Asio基本原理(CSDN也有Markdown了,好开森)
Boost.Asio基本原理 这一章涵盖了使用Boost.Asio时必须知道的一些事情.我们也将深入研究比同步编程更复杂.更有乐趣的异步编程. 网络API 这一部分包含了当使用Boost.Asio编写 ...
- Boost.Asio c++ 网络编程翻译(11)
*_at方法 这些方法在一个流上面做随机存取操作.你来指定read和write操作从什么地方開始(offset): async_read_at(stream, offset, buffer [, co ...
- boost::asio 使用实例
#include <iostream> #include <boost/asio.hpp> using namespace std; using namespace boost ...
- boost asio异步读写网络聊天程序client 实例具体解释
boost官方文档中聊天程序实例解说 数据包格式chat_message.hpp <pre name="code" class="cpp">< ...
- boost::asio的http client应用笔记
1 踩过的坑 1.1 io_service boost::asio::io_service::run()会一直运行到没有任务为止,假设中途调用stop().则全部等待中的任务会立马运行.要在停止的时候 ...
- BOOST.Asio——Tutorial
=================================版权声明================================= 版权声明:原创文章 谢绝转载 啥说的,鄙视那些无视版权随 ...
随机推荐
- hihocoder-1274 自行车架(高维dp)
时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi的宿舍楼下有一块用于停自行车的区域.平时自行车都停得非常杂乱,于是楼长打算去买一排自行车架用来停车.自行车架一般有P个 ...
- jspsmartupload 文件上传让input数据和文件上传同时提交
一.使用原因: 文件上传时,表单的属性中必须要有multipart/form-data,如以下例子: <form name="form_post" class="a ...
- centos下安装Mysql5.7.20
0.环境 本文操作系统: CentOS 7.2.1511 x86_64MySQL 版本: 5.7.16 1.卸载系统自带的 mariadb-lib [root@centos-linux ~]# rpm ...
- 1014 Waiting in Line (30)(30 分)
Suppose a bank has N windows open for service. There is a yellow line in front of the windows which ...
- NOIp2018集训test-10-18 (bike day4)
这是一套简单题,这几天的考试让bike老爷感觉很绝望,说实话我也确实不知道还能怎么更简单了. 这几天的题换做llj.sxy应该都能轻松AK吧,至少随便考个250+应该不是问题吧,我越来越觉得觉得我跟他 ...
- [转]前端网络(性能)监测工具berserkJS
berserkJS 是基于 Qt (C++跨平台库)开发的前端网络(性能)监测工具. 它的核心功能是通过内置 webkit 收集由页面实际网络请求相关数据. 偏重于页面上线前检测与评估. 页面性能分析 ...
- javascript自我测试题
javascript自我测试题--14道题而已! 地址:http://perfectionkills.com/javascript-quiz/ 司徒正美的答案解析:http://www.cnblogs ...
- virtual judge(专题一 简单搜索 A)
问题描述: Description 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘, ...
- oracle sql 语句 示例
--oracle 用户对象的导入导出 exp devimage/oracle@172.xx.x.xx/TESTDB owner='devimage' file=d:/devimage.dmp log= ...
- JavaScript设模式---单例模式
单例模式也称为单体模式,其中: 1,单体模式用于创建命名空间,将系列关联的属性和方法组织成一个逻辑单元,减少全局变量. 逻辑单元中的代码通过单一的变量进行访问. 2,三个特点: ① 该类只有一个实例: ...