(1)首先要初始化一个io_service,并且调用run方法运行起来
boost::asio::io_service iosrv;
iosrv.run();
(2)然后需要用一个iosrv的实例来初始化一个acceptor
boost::asio::ip::tcp::acceptor acceptor(iosrv);
(3)然后需要调用acceptor对象的open函数
boost::system::error_code ec;
acceptor.open(boost::asio::ip::tcp::v4(), ec);
(4)然后调用acceptor的bind函数绑定ip和端口,协议等
m_acceptor.set_option(boost::asio::socket_base::reuse_address(true) );
m_acceptor.bind(boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port), ec);
(5)然后调用accptor的listen函数进行监听
acceptor.listen(10);
(6)然后调用acceptor的async_accept函数异步接受一个连接
boost::asio::ip::tcp::socket m_sock;
m_acceptor.async_accept(m_sock, std::bind(&server::on_accept, this, std::placeholders::_1));
其中m_sock 接受新连接后保存连接信息的载体
需要注意的是,当接受一个连接完成后需要再次调用m_acceptor的async_accept函数,才会再次接受下一个连接,否则不会接受新的连接
(8)接收消息可以使用tcp::socket 对象的async_read_some方法(这个函数不一定读取锁期望的全部字节就可能返回)
void async_read()
{
auto self(shared_from_this());
m_socket.async_read_some(boost::asio::buffer(m_buff),
[this, self](const boost::system::error_code &ec, size_t byte_transffered) {
if (!ec)
{
async_write(byte_transffered);
}
else
{
std::cout << "read error" << ec << std::endl;
}
});
}
或者可以使用boost::asio::async_read方法,但是这个方法是读指定长度的数据,如果没有读到所期望的字节数,就不会返回,直到等到所有期待的字节或者出错的时候才返回,
boost::asio::async_read特别适合用来获取固定长度的包头和指定长度的包体,这个很适合解包
(9)发送消息可以用boost::asio::async_write()函数(不是socket类的成员函数)
void async_write(size_t byte_transffered)
{
auto self(shared_from_this());
boost::asio::async_write(m_socket, boost::asio::buffer(m_buff, byte_transffered),
[this, self](const boost::system::error_code &ec, size_t sendsize)
{
if (!ec)
{
std::cout << "send " << sendsize << " byte success." << std::endl;
async_read();
}
else
{
std::cout << "send fail." << std::endl;
}
}
);
}
如果初始化一个使用一个endpoint初始化一个acceptor,那么就不需要步骤(3)~(5),直接到调用acceptor::async_accept这一步,例如:
boost::asio::ip::tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), port))
asio的异步实现机制:asio库使用epoll模型之所以能做到全异步,是因为有个io_service这个类,这个类里面会维护一个待执行的任务队列,某个线程会调用这个io_service的run方法,run方法中一直循环检测任务队列,如果有未执行的队列就执行,其他线程通过io_service的post方法,把需要执行的函数加入到任务队列里面,让执行io_service.run()方法的那个线程去执行。这样就能做到异步,任务函数执行完后可以做一个回调通知函数post方
boost的每个socket都要绑定一个io_service就是这个道理
下面是echo服务端的代码:
// boost_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include
#include
#include
class session : public std::enable_shared_from_this
{
public:
session(boost::asio::ip::tcp::socket s) : m_socket(std::move(s))
{
}
void async_read()
{
auto self(shared_from_this());
m_socket.async_read_some(boost::asio::buffer(m_buff),
// boost::asio::async_read(m_socket, boost::asio::buffer(m_buff),
[this, self](const boost::system::error_code &ec, size_t byte_transffered) {
if (!ec)
{
std::string str(m_buff.data(), byte_transffered);
std::cout << "receive:" << str << std::endl;
async_write(byte_transffered);
}
else
{
std::cout << "read error" << ec << std::endl;
}
});
}
void async_write(size_t byte_transffered)
{
auto self(shared_from_this());
boost::asio::async_write(m_socket, boost::asio::buffer(m_buff, byte_transffered),
[this, self](const boost::system::error_code &ec, size_t sendsize)
{
if (!ec)
{
std::cout << "send " << sendsize << " byte success." << std::endl;
async_read();
}
else
{
std::cout << "send fail." << std::endl;
}
}
);
}
public:
boost::asio::ip::tcp::socket m_socket;
std::array m_buff;
};
class server {
public:
server(std::string ip, unsigned short port, boost::asio::io_service *pIoService):
m_sock(*pIoService), m_acceptor(*pIoService)
{
boost::system::error_code ec;
m_acceptor.open(boost::asio::ip::tcp::v4(), ec);
if (ec)
std::cout << "open error :" << ec << std::endl;
m_acceptor.set_option(boost::asio::socket_base::reuse_address(true) );
m_acceptor.bind(boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port), ec);
if (ec)
std::cout << "bind error :" << ec << std::endl;
std::cout << "port:" << port << std::endl;
m_acceptor.listen(10);
}
void async_accept()
{
m_acceptor.async_accept(m_sock, std::bind(&server::on_accept, this, std::placeholders::_1));
}
void on_accept(const boost::system::error_code &ec)
{
if (!ec)
{
std::shared_ptr ptr = std::make_shared(std::move(m_sock));
ptr->async_read();
}
//重新获取连接
async_accept();
}
public:
boost::asio::ip::tcp::socket m_sock;
boost::asio::ip::tcp::acceptor m_acceptor;
};
int main()
{
std::cout << "v2.2" << std::endl;
boost::asio::io_service ioservice;
server sv("", 9000, &ioservice);
sv.async_accept();
ioservice.run();
std::cout << "end" << std::endl;
}
参考博文:
https://www.cnblogs.com/hanerfan/p/5161955.html