// // tcp_server.cpp // ~~~~~~~~~~~~~~ // // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include #include #include #include #include #include #include #include #include using boost::asio::ip::tcp; #include class tcp_server : boost::asio::coroutine { public: tcp_server(tcp::acceptor& acceptor, std::size_t buf_size) : acceptor_(acceptor), socket_(acceptor_.get_executor()), buffer_(buf_size) { } void operator()(boost::system::error_code ec, std::size_t n = 0) { reenter (this) for (;;) { yield acceptor_.async_accept(socket_, ref(this)); while (!ec) { yield boost::asio::async_read(socket_, boost::asio::buffer(buffer_), ref(this)); if (!ec) { for (std::size_t i = 0; i < n; ++i) buffer_[i] = ~buffer_[i]; yield boost::asio::async_write(socket_, boost::asio::buffer(buffer_), ref(this)); } } socket_.close(); } } struct ref { explicit ref(tcp_server* p) : p_(p) { } void operator()(boost::system::error_code ec, std::size_t n = 0) { (*p_)(ec, n); } private: tcp_server* p_; }; private: tcp::acceptor& acceptor_; tcp::socket socket_; std::vector buffer_; tcp::endpoint sender_; }; #include int main(int argc, char* argv[]) { if (argc != 5) { std::fprintf(stderr, "Usage: tcp_server " " {spin|block}\n"); return 1; } unsigned short port = static_cast(std::atoi(argv[1])); int max_connections = std::atoi(argv[2]); std::size_t buf_size = std::atoi(argv[3]); bool spin = (std::strcmp(argv[4], "spin") == 0); boost::asio::io_context io_context(1); tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), port)); std::vector > servers; for (int i = 0; i < max_connections; ++i) { boost::shared_ptr s(new tcp_server(acceptor, buf_size)); servers.push_back(s); (*s)(boost::system::error_code()); } if (spin) for (;;) io_context.poll(); else io_context.run(); }