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