| src/examples/cpp03/timeouts/blocking_udp_client.cpp | src/examples/cpp11/timeouts/blocking_udp_client.cpp | 
| ⋮ | ⋮ | 
| 1  | // | 1  | // | 
| 2  | //·blocking_udp_client.cpp | 2  | //·blocking_udp_client.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/buffer.hpp" | 11  | #include·"asio/buffer.hpp" | 
| 12  | #include·"asio/io_context.hpp" | 12  | #include·"asio/io_context.hpp" | 
| 13  | #include·"asio/ip/udp.hpp" | 13  | #include·"asio/ip/udp.hpp" | 
| 14  | #include·<cstdlib> | 14  | #include·<cstdlib> | 
| 15  | #include·<boost/bind/bind.hpp> | 15  | #include·<functional> | 
| 16  | #include·<iostream> | 16  | #include·<iostream> | 
| 17  |  | 17  |  | 
| 18  | using·asio::ip::udp; | 18  | using·asio::ip::udp; | 
|   | 19  | using·std::placeholders::_1; | 
|   | 20  | using·std::placeholders::_2; | 
| 19  |  | 21  |  | 
| 20  | //---------------------------------------------------------------------- | 22  | //---------------------------------------------------------------------- | 
| 21  |  | 23  |  | 
| 22  | // | 24  | // | 
| 23  | //·This·class·manages·socket·timeouts·by·running·the·io_context·using·the·timed | 25  | //·This·class·manages·socket·timeouts·by·running·the·io_context·using·the·timed | 
| 24  | //·io_context::run_for()·member·function.·Each·asynchronous·operation·is·given | 26  | //·io_context::run_for()·member·function.·Each·asynchronous·operation·is·given | 
| 25  | //·a·timeout·within·which·it·must·complete.·The·socket·operations·themselves | 27  | //·a·timeout·within·which·it·must·complete.·The·socket·operations·themselves | 
| 26  | //·use·boost::bind·to·specify·the·completion·handler: | 28  | //·use·std::bind·to·specify·the·completion·handler: | 
| 27  | // | 29  | // | 
| 28  | //···+---------------+ | 30  | //···+---------------+ | 
| 29  | //···|···············| | 31  | //···|···············| | 
| 30  | //···|····receive····| | 32  | //···|····receive····| | 
| 31  | //···|···············| | 33  | //···|···············| | 
| 32  | //···+---------------+ | 34  | //···+---------------+ | 
| 33  | //···········| | 35  | //···········| | 
| 34  | //··async_-··|····+----------------+ | 36  | //··async_-··|····+----------------+ | 
| 35  | //·receive()·|····|················| | 37  | //·receive()·|····|················| | 
| 36  | //···········+--->|·handle_receive·| | 38  | //···········+--->|·handle_receive·| | 
| 37  | //················|················| | 39  | //················|················| | 
| 38  | //················+----------------+ | 40  | //················+----------------+ | 
| 39  | // | 41  | // | 
| 40  | //·For·a·given·socket·operation,·the·client·object·runs·the·io_context·to·block | 42  | //·For·a·given·socket·operation,·the·client·object·runs·the·io_context·to·block | 
| 41  | //·thread·execution·until·the·operation·completes·or·the·timeout·is·reached.·If | 43  | //·thread·execution·until·the·operation·completes·or·the·timeout·is·reached.·If | 
| 42  | //·the·io_context::run_for()·function·times·out,·the·socket·is·closed·and·the | 44  | //·the·io_context::run_for()·function·times·out,·the·socket·is·closed·and·the | 
| 43  | //·outstanding·asynchronous·operation·is·cancelled. | 45  | //·outstanding·asynchronous·operation·is·cancelled. | 
| 44  | // | 46  | // | 
| 45  | class·client | 47  | class·client | 
| 46  | { | 48  | { | 
| 47  | public: | 49  | public: | 
| 48  | ··client(const·udp::endpoint&·listen_endpoint) | 50  | ··client(const·udp::endpoint&·listen_endpoint) | 
| 49  | ····:·socket_(io_context_,·listen_endpoint) | 51  | ····:·socket_(io_context_,·listen_endpoint) | 
| 50  | ··{ | 52  | ··{ | 
| 51  | ··} | 53  | ··} | 
| 52  |  | 54  |  | 
| 53  | ··std::size_t·receive(const·asio::mutable_buffer&·buffer, | 55  | ··std::size_t·receive(const·asio::mutable_buffer&·buffer, | 
| 54  | ······asio::chrono::steady_clock::duration·timeout, | 56  | ······std::chrono::steady_clock::duration·timeout, | 
| 55  | ······asio::error_code&·ec) | 57  | ······std::error_code&·error) | 
| 56  | ··{ | 58  | ··{ | 
| 57  | ····//·Start·the·asynchronous·operation.·The·handle_receive·function·used·as·a | 59  | ····//·Start·the·asynchronous·operation.·The·handle_receive·function·used·as·a | 
| 58  | ····//·callback·will·update·the·ec·and·length·variables. | 60  | ····//·callback·will·update·the·error·and·length·variables. | 
| 59  | ····std::size_t·length·=·0; | 61  | ····std::size_t·length·=·0; | 
| 60  | ····socket_.async_receive(asio::buffer(buffer), | 62  | ····socket_.async_receive(asio::buffer(buffer), | 
| 61  | ········boost::bind(&client::handle_receive, | 63  | ········std::bind(&client::handle_receive,·_1,·_2,·&error,·&length)); | 
| 62  | ··········boost::placeholders::_1,·boost::placeholders::_2,·&ec,·&length)); |  | 
| 63  |  | 64  |  | 
| 64  | ····//·Run·the·operation·until·it·completes,·or·until·the·timeout. | 65  | ····//·Run·the·operation·until·it·completes,·or·until·the·timeout. | 
| 65  | ····run(timeout); | 66  | ····run(timeout); | 
| 66  |  | 67  |  | 
| 67  | ····return·length; | 68  | ····return·length; | 
| 68  | ··} | 69  | ··} | 
| 69  |  | 70  |  | 
| 70  | private: | 71  | private: | 
| 71  | ··void·run(asio::chrono::steady_clock::duration·timeout) | 72  | ··void·run(std::chrono::steady_clock::duration·timeout) | 
| 72  | ··{ | 73  | ··{ | 
| 73  | ····//·Restart·the·io_context,·as·it·may·have·been·left·in·the·"stopped"·state | 74  | ····//·Restart·the·io_context,·as·it·may·have·been·left·in·the·"stopped"·state | 
| 74  | ····//·by·a·previous·operation. | 75  | ····//·by·a·previous·operation. | 
| 75  | ····io_context_.restart(); | 76  | ····io_context_.restart(); | 
| 76  |  | 77  |  | 
| 77  | ····//·Block·until·the·asynchronous·operation·has·completed,·or·timed·out.·If | 78  | ····//·Block·until·the·asynchronous·operation·has·completed,·or·timed·out.·If | 
| 78  | ····//·the·pending·asynchronous·operation·is·a·composed·operation,·the·deadline | 79  | ····//·the·pending·asynchronous·operation·is·a·composed·operation,·the·deadline | 
| 79  | ····//·applies·to·the·entire·operation,·rather·than·individual·operations·on | 80  | ····//·applies·to·the·entire·operation,·rather·than·individual·operations·on | 
| 80  | ····//·the·socket. | 81  | ····//·the·socket. | 
| 81  | ····io_context_.run_for(timeout); | 82  | ····io_context_.run_for(timeout); | 
| 82  |  | 83  |  | 
| 83  | ····//·If·the·asynchronous·operation·completed·successfully·then·the·io_context | 84  | ····//·If·the·asynchronous·operation·completed·successfully·then·the·io_context | 
| 84  | ····//·would·have·been·stopped·due·to·running·out·of·work.·If·it·was·not | 85  | ····//·would·have·been·stopped·due·to·running·out·of·work.·If·it·was·not | 
| 85  | ····//·stopped,·then·the·io_context::run_for·call·must·have·timed·out. | 86  | ····//·stopped,·then·the·io_context::run_for·call·must·have·timed·out. | 
| 86  | ····if·(!io_context_.stopped()) | 87  | ····if·(!io_context_.stopped()) | 
| 87  | ····{ | 88  | ····{ | 
| 88  | ······//·Cancel·the·outstanding·asynchronous·operation. | 89  | ······//·Cancel·the·outstanding·asynchronous·operation. | 
| 89  | ······socket_.cancel(); | 90  | ······socket_.cancel(); | 
| 90  |  | 91  |  | 
| 91  | ······//·Run·the·io_context·again·until·the·operation·completes. | 92  | ······//·Run·the·io_context·again·until·the·operation·completes. | 
| 92  | ······io_context_.run(); | 93  | ······io_context_.run(); | 
| 93  | ····} | 94  | ····} | 
| 94  | ··} | 95  | ··} | 
| 95  |  | 96  |  | 
| 96  | ··static·void·handle_receive( | 97  | ··static·void·handle_receive( | 
| 97  | ······const·asio::error_code&·ec,·std::size_t·length, | 98  | ······const·std::error_code&·error,·std::size_t·length, | 
| 98  | ······asio::error_code*·out_ec,·std::size_t*·out_length) | 99  | ······std::error_code*·out_error,·std::size_t*·out_length) | 
| 99  | ··{ | 100  | ··{ | 
| 100  | ····*out_ec·=·ec; | 101  | ····*out_error·=·error; | 
| 101  | ····*out_length·=·length; | 102  | ····*out_length·=·length; | 
| 102  | ··} | 103  | ··} | 
| 103  |  | 104  |  | 
| 104  | private: | 105  | private: | 
| 105  | ··asio::io_context·io_context_; | 106  | ··asio::io_context·io_context_; | 
| 106  | ··udp::socket·socket_; | 107  | ··udp::socket·socket_; | 
| 107  | }; | 108  | }; | 
| 108  |  | 109  |  | 
| 109  | //---------------------------------------------------------------------- | 110  | //---------------------------------------------------------------------- | 
| 110  |  | 111  |  | 
| 111  | int·main(int·argc,·char*·argv[]) | 112  | int·main(int·argc,·char*·argv[]) | 
| 112  | { | 113  | { | 
| 113  | ··try | 114  | ··try | 
| 114  | ··{ | 115  | ··{ | 
| 115  | ····using·namespace·std;·//·For·atoi. | 116  | ····using·namespace·std;·//·For·atoi. | 
| 116  |  | 117  |  | 
| 117  | ····if·(argc·!=·3) | 118  | ····if·(argc·!=·3) | 
| 118  | ····{ | 119  | ····{ | 
| 119  | ······std::cerr·<<·"Usage:·blocking_udp_client·<listen_addr>·<listen_port>\n"; | 120  | ······std::cerr·<<·"Usage:·blocking_udp_client·<listen_addr>·<listen_port>\n"; | 
| 120  | ······return·1; | 121  | ······return·1; | 
| 121  | ····} | 122  | ····} | 
| 122  |  | 123  |  | 
| 123  | ····udp::endpoint·listen_endpoint( | 124  | ····udp::endpoint·listen_endpoint( | 
| 124  | ········asio::ip::make_address(argv[1]), | 125  | ········asio::ip::make_address(argv[1]), | 
| 125  | ········std::atoi(argv[2])); | 126  | ········std::atoi(argv[2])); | 
| 126  |  | 127  |  | 
| 127  | ····client·c(listen_endpoint); | 128  | ····client·c(listen_endpoint); | 
| 128  |  | 129  |  | 
| 129  | ····for·(;;) | 130  | ····for·(;;) | 
| 130  | ····{ | 131  | ····{ | 
| 131  | ······char·data[1024]; | 132  | ······char·data[1024]; | 
| 132  | ······asio::error_code·ec; | 133  | ······std::error_code·error; | 
| 133  | ······std::size_t·n·=·c.receive(asio::buffer(data), | 134  | ······std::size_t·n·=·c.receive(asio::buffer(data), | 
| 134  | ··········asio::chrono::seconds(10),·ec); | 135  | ··········std::chrono::seconds(10),·error); | 
| 135  |  | 136  |  | 
| 136  | ······if·(ec) | 137  | ······if·(error) | 
| 137  | ······{ | 138  | ······{ | 
| 138  | ········std::cout·<<·"Receive·error:·"·<<·ec.message()·<<·"\n";· | 139  | ········std::cout·<<·"Receive·error:·"·<<·error.message()·<<·"\n";· | 
| 139  | ······} | 140  | ······} | 
| 140  | ······else | 141  | ······else | 
| 141  | ······{ | 142  | ······{ | 
| 142  | ········std::cout·<<·"Received:·"; | 143  | ········std::cout·<<·"Received:·"; | 
| 143  | ········std::cout.write(data,·n); | 144  | ········std::cout.write(data,·n); | 
| 144  | ········std::cout·<<·"\n"; | 145  | ········std::cout·<<·"\n"; | 
| 145  | ······} | 146  | ······} | 
| 146  | ····} | 147  | ····} | 
| 147  | ··} | 148  | ··} | 
| 148  | ··catch·(std::exception&·e) | 149  | ··catch·(std::exception&·e) | 
| 149  | ··{ | 150  | ··{ | 
| 150  | ····std::cerr·<<·"Exception:·"·<<·e.what()·<<·"\n"; | 151  | ····std::cerr·<<·"Exception:·"·<<·e.what()·<<·"\n"; | 
| 151  | ··} | 152  | ··} | 
| 152  |  | 153  |  | 
| 153  | ··return·0; | 154  | ··return·0; | 
| 154  | } | 155  | } |