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-​2018·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2018·​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.​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,​·​_1,​·​_2,​·​&ec,​·​&length)​)​;​63 ········​std:​:​bind(&client:​:​handle_receive,​·​_1,​·​_2,​·​&error,​·​&length)​)​;​
62 64
63 ····​/​/​·​Run·​the·​operation·​until·​it·​completes,​·​or·​until·​the·​timeout.​65 ····​/​/​·​Run·​the·​operation·​until·​it·​completes,​·​or·​until·​the·​timeout.​
64 ····​run(timeout)​;​66 ····​run(timeout)​;​
65 67
66 ····​return·​length;​68 ····​return·​length;​
67 ··​}69 ··​}
68 70
69 private:​71 private:​
70 ··​void·​run(asio:​:​chrono:​:​steady_clock:​:​duration·​timeout)​72 ··​void·​run(std:​:​chrono:​:​steady_clock:​:​duration·​timeout)​
71 ··​{73 ··​{
72 ····​/​/​·​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
73 ····​/​/​·​by·​a·​previous·​operation.​75 ····​/​/​·​by·​a·​previous·​operation.​
74 ····​io_context_.​restart()​;​76 ····​io_context_.​restart()​;​
75 77
76 ····​/​/​·​Block·​until·​the·​asynchronous·​operation·​has·​completed,​·​or·​timed·​out.​·​If78 ····​/​/​·​Block·​until·​the·​asynchronous·​operation·​has·​completed,​·​or·​timed·​out.​·​If
77 ····​/​/​·​the·​pending·​asynchronous·​operation·​is·​a·​composed·​operation,​·​the·​deadline79 ····​/​/​·​the·​pending·​asynchronous·​operation·​is·​a·​composed·​operation,​·​the·​deadline
78 ····​/​/​·​applies·​to·​the·​entire·​operation,​·​rather·​than·​individual·​operations·​on80 ····​/​/​·​applies·​to·​the·​entire·​operation,​·​rather·​than·​individual·​operations·​on
79 ····​/​/​·​the·​socket.​81 ····​/​/​·​the·​socket.​
80 ····​io_context_.​run_for(timeout)​;​82 ····​io_context_.​run_for(timeout)​;​
81 83
82 ····​/​/​·​If·​the·​asynchronous·​operation·​completed·​successfully·​then·​the·​io_context84 ····​/​/​·​If·​the·​asynchronous·​operation·​completed·​successfully·​then·​the·​io_context
83 ····​/​/​·​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
84 ····​/​/​·​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.​
85 ····​if·​(!io_context_.​stopped()​)​87 ····​if·​(!io_context_.​stopped()​)​
86 ····​{88 ····​{
87 ······​/​/​·​Cancel·​the·​outstanding·​asynchronous·​operation.​89 ······​/​/​·​Cancel·​the·​outstanding·​asynchronous·​operation.​
88 ······​socket_.​cancel()​;​90 ······​socket_.​cancel()​;​
89 91
90 ······​/​/​·​Run·​the·​io_context·​again·​until·​the·​operation·​completes.​92 ······​/​/​·​Run·​the·​io_context·​again·​until·​the·​operation·​completes.​
91 ······​io_context_.​run()​;​93 ······​io_context_.​run()​;​
92 ····​}94 ····​}
93 ··​}95 ··​}
94 96
95 ··​static·​void·​handle_receive(97 ··​static·​void·​handle_receive(
96 ······​const·asio:​:​error_code&·​ec,​·​std:​:​size_t·​length,​98 ······​const·​std:​:​error_code&·​error,​·​std:​:​size_t·​length,​
97 ······asio:​:​error_code*·​out_ec,​·​std:​:​size_t*·​out_length)​99 ······​std:​:​error_code*·​out_error,​·​std:​:​size_t*·​out_length)​
98 ··​{100 ··​{
99 ····​*out_ec·​=·​ec;​101 ····​*out_error·​=·​error;​
100 ····​*out_length·​=·​length;​102 ····​*out_length·​=·​length;​
101 ··​}103 ··​}
102 104
103 private:​105 private:​
104 ··​asio:​:​io_context·​io_context_;​106 ··​asio:​:​io_context·​io_context_;​
105 ··​udp:​:​socket·​socket_;​107 ··​udp:​:​socket·​socket_;​
106 };​108 };​
107 109
108 /​/​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​110 /​/​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​
109 111
110 int·​main(int·​argc,​·​char*·​argv[])​112 int·​main(int·​argc,​·​char*·​argv[])​
111 {113 {
112 ··​try114 ··​try
113 ··​{115 ··​{
114 ····​using·​namespace·​std;​·​/​/​·​For·​atoi.​116 ····​using·​namespace·​std;​·​/​/​·​For·​atoi.​
115 117
116 ····​if·​(argc·​!=·​3)​118 ····​if·​(argc·​!=·​3)​
117 ····​{119 ····​{
118 ······​std:​:​cerr·​<<·​"Usage:​·​blocking_udp_client·​<listen_addr>·​<listen_port>\n";​120 ······​std:​:​cerr·​<<·​"Usage:​·​blocking_udp_client·​<listen_addr>·​<listen_port>\n";​
119 ······​return·​1;​121 ······​return·​1;​
120 ····​}122 ····​}
121 123
122 ····​udp:​:​endpoint·​listen_endpoint(124 ····​udp:​:​endpoint·​listen_endpoint(
123 ········​asio:​:​ip:​:​make_address(argv[1])​,​125 ········​asio:​:​ip:​:​make_address(argv[1])​,​
124 ········​std:​:​atoi(argv[2])​)​;​126 ········​std:​:​atoi(argv[2])​)​;​
125 127
126 ····​client·​c(listen_endpoint)​;​128 ····​client·​c(listen_endpoint)​;​
127 129
128 ····​for·​(;​;​)​130 ····​for·​(;​;​)​
129 ····​{131 ····​{
130 ······​char·​data[1024];​132 ······​char·​data[1024];​
131 ······asio:​:​error_code·​ec;​133 ······​std:​:​error_code·​error;​
132 ······​std:​:​size_t·​n·​=·​c.​receive(asio:​:​buffer(data)​,​134 ······​std:​:​size_t·​n·​=·​c.​receive(asio:​:​buffer(data)​,​
133 ··········asio:​:​chrono:​:​seconds(10)​,​·​ec)​;​135 ··········​std:​:​chrono:​:​seconds(10)​,​·​error)​;​
134 136
135 ······​if·​(ec)​137 ······​if·​(error)​
136 ······​{138 ······​{
137 ········​std:​:​cout·​<<·​"Receive·​error:​·​"·​<<·​ec.​message()​·​<<·​"\n";​·139 ········​std:​:​cout·​<<·​"Receive·​error:​·​"·​<<·​error.​message()​·​<<·​"\n";​·
138 ······​}140 ······​}
139 ······​else141 ······​else
140 ······​{142 ······​{
141 ········​std:​:​cout·​<<·​"Received:​·​";​143 ········​std:​:​cout·​<<·​"Received:​·​";​
142 ········​std:​:​cout.​write(data,​·​n)​;​144 ········​std:​:​cout.​write(data,​·​n)​;​
143 ········​std:​:​cout·​<<·​"\n";​145 ········​std:​:​cout·​<<·​"\n";​
144 ······​}146 ······​}
145 ····​}147 ····​}
146 ··​}148 ··​}
147 ··​catch·​(std:​:​exception&·​e)​149 ··​catch·​(std:​:​exception&·​e)​
148 ··​{150 ··​{
149 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​151 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​
150 ··​}152 ··​}
151 153
152 ··​return·​0;​154 ··​return·​0;​
153 }155 }