| src/examples/cpp03/spawn/echo_server.cpp | src/examples/cpp11/spawn/echo_server.cpp | 
| ⋮ | ⋮ | 
| 1  | // | 1  | // | 
| 2  | //·echo_server.cpp | 2  | //·echo_server.cpp | 
| 3  | //·~~~~~~~~~~~~~~~ | 3  | //·~~~~~~~~~~~~~~~ | 
| 4  | // | 4  | // | 
| 5  | //·Copyright·(c)·2003-2023·Christopher·M.·Kohlhoff·(chris·at·kohlhoff·dot·com) | 5  | //·Copyright·(c)·2003-2023·Christopher·M.·Kohlhoff·(chris·at·kohlhoff·dot·com) | 
| 6  | // | 6  | // | 
| 7  | //·Distributed·under·the·Boost·Software·License,·Version·1.0.·(See·accompanying | 7  | //·Distributed·under·the·Boost·Software·License,·Version·1.0.·(See·accompanying | 
| 8  | //·file·LICENSE_1_0.txt·or·copy·at·http://www.boost.org/LICENSE_1_0.txt) | 8  | //·file·LICENSE_1_0.txt·or·copy·at·http://www.boost.org/LICENSE_1_0.txt) | 
| 9  | // | 9  | // | 
| 10  |  | 10  |  | 
| 11  | #include·<asio/detached.hpp> | 11  | #include·<asio/detached.hpp> | 
| 12  | #include·<asio/io_context.hpp> | 12  | #include·<asio/io_context.hpp> | 
| 13  | #include·<asio/ip/tcp.hpp> | 13  | #include·<asio/ip/tcp.hpp> | 
| 14  | #include·<asio/spawn.hpp> | 14  | #include·<asio/spawn.hpp> | 
| 15  | #include·<asio/steady_timer.hpp> | 15  | #include·<asio/steady_timer.hpp> | 
| 16  | #include·<asio/write.hpp> | 16  | #include·<asio/write.hpp> | 
| 17  | #include·<boost/bind/bind.hpp> |  | 
| 18  | #include·<boost/shared_ptr.hpp> |  | 
| 19  | #include·<boost/enable_shared_from_this.hpp> |  | 
| 20  | #include·<iostream> | 17  | #include·<iostream> | 
|   | 18  | #include·<memory> | 
| 21  |  | 19  |  | 
| 22  | using·asio::ip::tcp; | 20  | using·asio::ip::tcp; | 
| 23  |  | 21  |  | 
| 24  | class·session·:·public·boost::enable_shared_from_this<session> | 22  | class·session·:·public·std::enable_shared_from_this<session> | 
| 25  | { | 23  | { | 
| 26  | public: | 24  | public: | 
| 27  | ··explicit·session(asio::io_context&·io_context) | 25  | ··explicit·session(asio::io_context&·io_context,·tcp::socket·socket) | 
| 28  | ····:·strand_(asio::make_strand(io_context)), | 26  | ····:·socket_(std::move(socket)), | 
| 29  | ······socket_(io_context), | 27  | ······timer_(io_context), | 
| 30  | ······timer_(io_context) | 28  | ······strand_(io_context.get_executor()) | 
| 31  | ··{ | 29  | ··{ | 
| 32  | ··} | 30  | ··} | 
| 33  |  | 31  |  | 
| 34  | ··tcp::socket&·socket() |  | 
| 35  | ··{ |  | 
| 36  | ····return·socket_; |  | 
| 37  | ··} |  | 
| 38  |  |  | 
| 39  | ··void·go() | 32  | ··void·go() | 
| 40  | ··{ | 33  | ··{ | 
|   | 34  | ····auto·self(shared_from_this()); | 
| 41  | ····asio::spawn(strand_, | 35  | ····asio::spawn(strand_, | 
| 42  | ········boost::bind(&session::echo, | 36  | ········[this,·self](asio::yield_context·yield) | 
| 43  | ··········shared_from_this(),·boost::placeholders::_1), | 37  | ········{ | 
| 44  | ········asio::detached_t()); | 38  | ··········try | 
|   | 39  | ··········{ | 
|   | 40  | ············char·data[128]; | 
|   | 41  | ············for·(;;) | 
|   | 42  | ············{ | 
|   | 43  | ··············timer_.expires_after(std::chrono::seconds(10)); | 
|   | 44  | ··············std::size_t·n·=·socket_.async_read_some(asio::buffer(data),·yield); | 
|   | 45  | ··············asio::async_write(socket_,·asio::buffer(data,·n),·yield); | 
|   | 46  | ············} | 
|   | 47  | ··········} | 
|   | 48  | ··········catch·(std::exception&·e) | 
|   | 49  | ··········{ | 
|   | 50  | ············socket_.close(); | 
|   | 51  | ············timer_.cancel(); | 
|   | 52  | ··········} | 
|   | 53  | ········},·asio::detached); | 
|   | 54  |  | 
| 45  | ····asio::spawn(strand_, | 55  | ····asio::spawn(strand_, | 
| 46  | ········boost::bind(&session::timeout, | 56  | ········[this,·self](asio::yield_context·yield) | 
| 47  | ··········shared_from_this(),·boost::placeholders::_1), | 57  | ········{ | 
| 48  | ········asio::detached_t()); | 58  | ··········while·(socket_.is_open()) | 
|   | 59  | ··········{ | 
|   | 60  | ············asio::error_code·ignored_ec; | 
|   | 61  | ············timer_.async_wait(yield[ignored_ec]); | 
|   | 62  | ············if·(timer_.expiry()·<=·asio::steady_timer::clock_type::now()) | 
|   | 63  | ··············socket_.close(); | 
|   | 64  | ··········} | 
|   | 65  | ········},·asio::detached); | 
| 49  | ··} | 66  | ··} | 
| 50  |  | 67  |  | 
| 51  | private: | 68  | private: | 
| 52  | ··void·echo(asio::yield_context·yield) |  | 
| 53  | ··{ |  | 
| 54  | ····try |  | 
| 55  | ····{ |  | 
| 56  | ······char·data[128]; |  | 
| 57  | ······for·(;;) |  | 
| 58  | ······{ |  | 
| 59  | ········timer_.expires_after(asio::chrono::seconds(10)); |  | 
| 60  | ········std::size_t·n·=·socket_.async_read_some(asio::buffer(data),·yield); |  | 
| 61  | ········asio::async_write(socket_,·asio::buffer(data,·n),·yield); |  | 
| 62  | ······} |  | 
| 63  | ····} |  | 
| 64  | ····catch·(std::exception&·e) |  | 
| 65  | ····{ |  | 
| 66  | ······socket_.close(); |  | 
| 67  | ······timer_.cancel(); |  | 
| 68  | ····} |  | 
| 69  | ··} |  | 
| 70  |  |  | 
| 71  | ··void·timeout(asio::yield_context·yield) |  | 
| 72  | ··{ |  | 
| 73  | ····while·(socket_.is_open()) |  | 
| 74  | ····{ |  | 
| 75  | ······asio::error_code·ignored_ec; |  | 
| 76  | ······timer_.async_wait(yield[ignored_ec]); |  | 
| 77  | ······if·(timer_.expiry()·<=·asio::steady_timer::clock_type::now()) |  | 
| 78  | ········socket_.close(); |  | 
| 79  | ····} |  | 
| 80  | ··} |  | 
| 81  |  |  | 
| 82  | ··asio::strand<asio::io_context::executor_type>·strand_; |  | 
| 83  | ··tcp::socket·socket_; | 69  | ··tcp::socket·socket_; | 
| 84  | ··asio::steady_timer·timer_; | 70  | ··asio::steady_timer·timer_; | 
|   | 71  | ··asio::strand<asio::io_context::executor_type>·strand_; | 
| 85  | }; | 72  | }; | 
| 86  |  | 73  |  | 
| 87  | void·do_accept(asio::io_context&·io_context, |  | 
| 88  | ····unsigned·short·port,·asio::yield_context·yield) |  | 
| 89  | { |  | 
| 90  | ··tcp::acceptor·acceptor(io_context,·tcp::endpoint(tcp::v4(),·port)); |  | 
| 91  |  |  | 
| 92  | ··for·(;;) |  | 
| 93  | ··{ |  | 
| 94  | ····asio::error_code·ec; |  | 
| 95  | ····boost::shared_ptr<session>·new_session(new·session(io_context)); |  | 
| 96  | ····acceptor.async_accept(new_session->socket(),·yield[ec]); |  | 
| 97  | ····if·(!ec)·new_session->go(); |  | 
| 98  | ··} |  | 
| 99  | } |  | 
| 100  |  |  | 
| 101  | int·main(int·argc,·char*·argv[]) | 74  | int·main(int·argc,·char*·argv[]) | 
| 102  | { | 75  | { | 
| 103  | ··try | 76  | ··try | 
| 104  | ··{ | 77  | ··{ | 
| 105  | ····if·(argc·!=·2) | 78  | ····if·(argc·!=·2) | 
| 106  | ····{ | 79  | ····{ | 
| 107  | ······std::cerr·<<·"Usage:·echo_server·<port>\n"; | 80  | ······std::cerr·<<·"Usage:·echo_server·<port>\n"; | 
| 108  | ······return·1; | 81  | ······return·1; | 
| 109  | ····} | 82  | ····} | 
| 110  |  | 83  |  | 
| 111  | ····asio::io_context·io_context; | 84  | ····asio::io_context·io_context; | 
| 112  |  | 85  |  | 
| 113  | ····asio::spawn(io_context, | 86  | ····asio::spawn(io_context, | 
| 114  | ········boost::bind(do_accept,·boost::ref(io_context), | 87  | ········[&](asio::yield_context·yield) | 
| 115  | ··········atoi(argv[1]),·boost::placeholders::_1), | 88  | ········{ | 
| 116  | ········asio::detached_t()); | 89  | ··········tcp::acceptor·acceptor(io_context, | 
|   | 90  | ············tcp::endpoint(tcp::v4(),·std::atoi(argv[1]))); | 
|   | 91  |  | 
|   | 92  | ··········for·(;;) | 
|   | 93  | ··········{ | 
|   | 94  | ············asio::error_code·ec; | 
|   | 95  | ············tcp::socket·socket(io_context); | 
|   | 96  | ············acceptor.async_accept(socket,·yield[ec]); | 
|   | 97  | ············if·(!ec) | 
|   | 98  | ············{ | 
|   | 99  | ··············std::make_shared<session>(io_context,·std::move(socket))->go(); | 
|   | 100  | ············} | 
|   | 101  | ··········} | 
|   | 102  | ········}, | 
|   | 103  | ········[](std::exception_ptr·e) | 
|   | 104  | ········{ | 
|   | 105  | ··········if·(e) | 
|   | 106  | ············std::rethrow_exception(e); | 
|   | 107  | ········}); | 
| 117  |  | 108  |  | 
| 118  | ····io_context.run(); | 109  | ····io_context.run(); | 
| 119  | ··} | 110  | ··} | 
| 120  | ··catch·(std::exception&·e) | 111  | ··catch·(std::exception&·e) | 
| 121  | ··{ | 112  | ··{ | 
| 122  | ····std::cerr·<<·"Exception:·"·<<·e.what()·<<·"\n"; | 113  | ····std::cerr·<<·"Exception:·"·<<·e.what()·<<·"\n"; | 
| 123  | ··} | 114  | ··} | 
| 124  |  | 115  |  | 
| 125  | ··return·0; | 116  | ··return·0; | 
| 126  | } | 117  | } |