src/​examples/​cpp03/​timeouts/​blocking_udp_client.​cppsrc/​examples/​cpp11/​timeouts/​blocking_udp_client.​cpp
1 /​/​1 /​/​
2 /​/​·​blocking_udp_client.​cpp2 /​/​·​blocking_udp_client.​cpp
3 /​/​·​~~~~~~~~~~~~~~~~~~~~~​~~3 /​/​·​~~~~~~~~~~~~~~~~~~~~~​~~
4 /​/​4 /​/​
5 /​/​·​Copyright·​(c)​·​2003-​2022·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2022·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​
6 /​/​6 /​/​
7 /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying7 /​/​·​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·​timed25 /​/​·​This·​class·​manages·​socket·​timeouts·​by·​running·​the·​io_context·​using·​the·​timed
24 /​/​·​io_context:​:​run_for()​·​member·​function.​·​Each·​asynchronous·​operation·​is·​given26 /​/​·​io_context:​:​run_for()​·​member·​function.​·​Each·​asynchronous·​operation·​is·​given
25 /​/​·​a·​timeout·​within·​which·​it·​must·​complete.​·​The·​socket·​operations·​themselves27 /​/​·​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·​block42 /​/​·​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.​·​If43 /​/​·​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·​the44 /​/​·​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·​client47 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·​a59 ····​/​/​·​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"·​state74 ····​/​/​·​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.​·​If78 ····​/​/​·​Block·​until·​the·​asynchronous·​operation·​has·​completed,​·​or·​timed·​out.​·​If
78 ····​/​/​·​the·​pending·​asynchronous·​operation·​is·​a·​composed·​operation,​·​the·​deadline79 ····​/​/​·​the·​pending·​asynchronous·​operation·​is·​a·​composed·​operation,​·​the·​deadline
79 ····​/​/​·​applies·​to·​the·​entire·​operation,​·​rather·​than·​individual·​operations·​on80 ····​/​/​·​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_context84 ····​/​/​·​If·​the·​asynchronous·​operation·​completed·​successfully·​then·​the·​io_context
84 ····​/​/​·​would·​have·​been·​stopped·​due·​to·​running·​out·​of·​work.​·​If·​it·​was·​not85 ····​/​/​·​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 ··​try114 ··​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 ······​else141 ······​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 }