Both the source code and the modified code are asynchronous and accept multiple connections. As you can see from the following snippet, the async_accept AcceptHandler operation initiates another async_accept operation, forming an asynchronous loop:
.-----------------------------------. V | void server::do_accept() | { | acceptor_.async_accept(..., | [this](boost::system::error_code ec) | { |
sleep() in a session ReadHandler causes a single thread on which io_service is io_service to block until sleep completes. Therefore, the program will do nothing. However, this does not result in the cancellation of any outstanding transactions. For a better understanding of asynchronous operations and io_service consider the answer question this .
Here is an example of a server that handles multiple connections. It generates a stream that creates 5 client sockets and connects them to the server.
#include <cstdlib> #include <iostream> #include <memory> #include <utility> #include <vector> #include <boost/asio.hpp> #include <boost/thread.hpp> using boost::asio::ip::tcp; class session : public std::enable_shared_from_this<session> { public: session(tcp::socket socket) : socket_(std::move(socket)) { } ~session() { std::cout << "session ended" << std::endl; } void start() { std::cout << "session started" << std::endl; do_read(); } private: void do_read() { auto self(shared_from_this()); socket_.async_read_some(boost::asio::buffer(data_, max_length), [this, self](boost::system::error_code ec, std::size_t length) { if (!ec) { do_write(length); } }); } void do_write(std::size_t length) { auto self(shared_from_this()); boost::asio::async_write(socket_, boost::asio::buffer(data_, length), [this, self](boost::system::error_code ec, std::size_t /*length*/) { if (!ec) { do_read(); } }); } tcp::socket socket_; enum { max_length = 1024 }; char data_[max_length]; }; class server { public: server(boost::asio::io_service& io_service, short port) : acceptor_(io_service, tcp::endpoint(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(); }); } tcp::acceptor acceptor_; tcp::socket socket_; }; int main(int argc, char* argv[]) { try { if (argc != 2) { std::cerr << "Usage: async_tcp_echo_server <port>\n"; return 1; } boost::asio::io_service io_service; auto port = std::atoi(argv[1]); server s(io_service, port); boost::thread client_main( [&io_service, port] { tcp::endpoint server_endpoint( boost::asio::ip::address_v4::loopback(), port); // Create and connect 5 clients to the server. std::vector<std::shared_ptr<tcp::socket>> clients; for (auto i = 0; i < 5; ++i) { auto client = std::make_shared<tcp::socket>( std::ref(io_service)); client->connect(server_endpoint); clients.push_back(client); } // Wait 2 seconds before destroying all clients. boost::this_thread::sleep(boost::posix_time::seconds(2)); }); io_service.run(); client_main.join(); } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << "\n"; } return 0; }
Exit:
session started session started session started session started session started session ended session ended session ended session ended session ended
Tanner sansbury
source share