asio::coro协程
很多使用boost::asio的同学觉得asio网络库写网络程序的时候,逻辑上很难理解,boost 1.53中asio带了一个coro类。asio::coro是协程的状态机实现,使用asio::coro可以用同步的逻辑写一步的代码,简化代码逻辑。
#include <boost/asio.hpp>
#include <iostream>
#include <memory>
#include <utility>
#include <vector>
#include <boost/asio/yield.hpp>
#include <boost/bind.hpp>
class shared_const_buffer
{
public:
// Construct from a std::string.
explicit shared_const_buffer(const std::string& data)
: data_(new std::vector<char>(data.begin(), data.end())),
buffer_(boost::asio::buffer(*data_))
{
}
// Implement the ConstBufferSequence requirements.
typedef boost::asio::const_buffer value_type;
typedef const boost::asio::const_buffer* const_iterator;
const boost::asio::const_buffer* begin() const { return &buffer_; }
const boost::asio::const_buffer* end() const { return &buffer_ + 1; }
private:
std::shared_ptr<std::vector<char> > data_;
boost::asio::const_buffer buffer_;
};
class session
: public std::enable_shared_from_this<session>
{
public:
session(boost::asio::ip::tcp::socket socket)
: socket_(std::move(socket))
{
}
~session()
{
socket_.close();
}
void start()
{
handler_process(boost::system::error_code(),0);
}
void handler_process(boost::system::error_code ec, size_t bytes_transferred)
{
std::time_t now = std::time(0);
shared_const_buffer buffer(std::ctime(&now));
if (ec)
{
return;
}
std::istream request_stream(&request_);
std::string recv_line;
reenter (&coro_) for (;;)
{
yield boost::asio::async_read_until(socket_, request_, "\r\n",
boost::bind(&session::handler_process, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
std::getline(request_stream, recv_line);
if(recv_line.substr(0, 4) == "time")
{
yield boost::asio::async_write(socket_, buffer,
boost::bind(&session::handler_process, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else if(recv_line.substr(0, 4) == "quit")
{
return;
}
}
}
private:
// The socket used to communicate with the client.
boost::asio::ip::tcp::socket socket_;
boost::asio::coroutine coro_;
boost::asio::streambuf request_;
};
class server
{
public:
server(boost::asio::io_service& io_service, short port)
: acceptor_(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
socket_(io_service)
{
do_accept();
}
private:
void do_accept()
{
acceptor_.async_accept(socket_,
[this](boost::system::error_code ec)
{
if (!ec)
{
std::make_shared<session>(std::move(socket_))->start();
}
do_accept();
});
}
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::ip::tcp::socket socket_;
};
int main(int argc, char* argv[])
{
try
{
if (argc != 2)
{
std::cerr << "Usage: coro <port>\n";
return 1;
}
boost::asio::io_service io_service;
server s(io_service, std::atoi(argv[1]));
std::cout << "started on tcp://127.0.0.1:" << argv[1] << "; press Ctrl-C to terminate." << std::endl;
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
编译命令:
gcc -o coro coro.cc -lstdc++ -lboost_system --std=c++0x
运行terminal1:
./coro 8001
运行terminal2:
telnet localhost 8001
结果:
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Thu Sep 12 20:53:10 2013
Thu Sep 12 20:53:10 2013
Connection closed by foreign host.