src/​examples/​cpp03/​timeouts/​blocking_token_tcp_cl​ient.​cppsrc/​examples/​cpp11/​timeouts/​blocking_token_tcp_cl​ient.​cpp
1 /​/​1 /​/​
2 /​/​·​blocking_token_tcp_cl​ient.​cpp2 /​/​·​blocking_token_tcp_cl​ient.​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·​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/​connect.​hpp"11 #include·​"asio/​connect.​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/​read_until.​hpp"14 #include·​"asio/​read_until.​hpp"
15 #include·​"asio/​streambuf.​hpp"15 #include·​"asio/​streambuf.​hpp"
16 #include·​"asio/​system_error.​hpp"16 #include·​"asio/​system_error.​hpp"
17 #include·​"asio/​write.​hpp"17 #include·​"asio/​write.​hpp"
18 #include·​<cstdlib>18 #include·​<cstdlib>
19 #include·​<iostream>19 #include·​<iostream>
20 #include·​<memory>20 #include·​<memory>
21 #include·​<string>21 #include·​<string>
22 22
23 using·​asio:​:​ip:​:​tcp;​23 using·​asio:​:​ip:​:​tcp;​
24 24
25 /​/​·​We·​will·​use·​our·​sockets·​only·​with·​an·​io_context.​25 /​/​·​We·​will·​use·​our·​sockets·​only·​with·​an·​io_context.​
26 typedef·​asio:​:​basic_stream_socket<t​cp,​26 using·tcp_socket·=·​asio:​:​basic_stream_socket<
27 ····​asio:​:​io_context:​:​executor_type>·tcp_socket;​27 ····tcp,​·​asio:​:​io_context:​:​executor_type>;​
28 28
29 /​/​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​29 /​/​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​
30 30
31 /​/​·​A·​custom·​completion·​token·​that·​makes·​asynchronous·​operations·​behave·​as31 /​/​·​A·​custom·​completion·​token·​that·​makes·​asynchronous·​operations·​behave·​as
32 /​/​·​though·​they·​are·​blocking·​calls·​with·​a·​timeout.​32 /​/​·​though·​they·​are·​blocking·​calls·​with·​a·​timeout.​
33 struct·​close_after33 struct·​close_after
34 {34 {
35 ··​close_after(asio:​:​chrono:​:​steady_clock:​:​duration·​t,​·​tcp_socket&·​s)​35 ··​close_after(std:​:​chrono:​:​steady_clock:​:​duration·​t,​·​tcp_socket&·​s)​
36 ····​:​·​timeout_(t)​,​·​socket_(s)​36 ····​:​·​timeout_(t)​,​·​socket_(s)​
37 ··​{37 ··​{
38 ··​}38 ··​}
39 39
40 ··​/​/​·​The·​maximum·​time·​to·​wait·​for·​an·​asynchronous·​operation·​to·​complete.​40 ··​/​/​·​The·​maximum·​time·​to·​wait·​for·​an·​asynchronous·​operation·​to·​complete.​
41 ··asio:​:​chrono:​:​steady_clock:​:​duration·​timeout_;​41 ··​std:​:​chrono:​:​steady_clock:​:​duration·​timeout_;​
42 42
43 ··​/​/​·​The·​socket·​to·​be·​closed·​if·​the·​operation·​does·​not·​complete·​in·​time.​43 ··​/​/​·​The·​socket·​to·​be·​closed·​if·​the·​operation·​does·​not·​complete·​in·​time.​
44 ··​tcp_socket&·​socket_;​44 ··​tcp_socket&·​socket_;​
45 };​45 };​
46 46
47 namespace·​asio·​{47 namespace·​asio·​{
48 48
49 /​/​·​The·​async_result·​template·​is·​specialised·​to·​allow·​the·​close_after·​token·​to49 /​/​·​The·​async_result·​template·​is·​specialised·​to·​allow·​the·​close_after·​token·​to
50 /​/​·​be·​used·​with·​asynchronous·​operations·​that·​have·​a·​completion·​signature·​of50 /​/​·​be·​used·​with·​asynchronous·​operations·​that·​have·​a·​completion·​signature·​of
51 /​/​·​void(error_code,​·​T)​.​·​Generalising·​this·​for·​all·​completion·​signature·​forms·​is51 /​/​·​void(error_code,​·​T)​.​·​Generalising·​this·​for·​all·​completion·​signature·​forms·​is
52 /​/​·​left·​as·​an·​exercise·​for·​the·​reader.​52 /​/​·​left·​as·​an·​exercise·​for·​the·​reader.​
53 template·​<typename·​T>53 template·​<typename·​T>
54 class·​async_result<close_af​ter,​·​void(asio:​:​error_code,​·​T)​>54 class·​async_result<close_af​ter,​·​void(std:​:​error_code,​·​T)​>
55 {55 {
56 public:​56 public:​
57 ··​/​/​·​An·​asynchronous·​operation's·​initiating·​function·​automatically·​creates·​an57 ··​/​/​·​An·​asynchronous·​operation's·​initiating·​function·​automatically·​creates·​an
58 ··​/​/​·​completion_handler_ty​pe·​object·​from·​the·​token.​·​This·​function·​object·​is58 ··​/​/​·​completion_handler_ty​pe·​object·​from·​the·​token.​·​This·​function·​object·​is
59 ··​/​/​·​then·​called·​on·​completion·​of·​the·​asynchronous·​operation.​59 ··​/​/​·​then·​called·​on·​completion·​of·​the·​asynchronous·​operation.​
60 ··​class·​completion_handler_ty​pe60 ··​class·​completion_handler_ty​pe
61 ··​{61 ··​{
62 ··​public:​62 ··​public:​
63 ····​completion_handler_ty​pe(const·​close_after&·​token)​63 ····​completion_handler_ty​pe(const·​close_after&·​token)​
64 ······​:​·​token_(token)​64 ······​:​·​token_(token)​
65 ····​{65 ····​{
66 ····​}66 ····​}
67 67
68 ····​void·​operator()​(asio:​:​error_code·​ec,​·​T·​t)​68 ····​void·​operator()​(const·std:​:​error_code&·​error,​·​T·​t)​
69 ····​{69 ····​{
70 ······​*ec_·​=·​ec;​70 ······​*error_·​=·​error;​
71 ······​*t_·​=·​t;​71 ······​*t_·​=·​t;​
72 ····​}72 ····​}
73 73
74 ··​private:​74 ··​private:​
75 ····​friend·​class·​async_result;​75 ····​friend·​class·​async_result;​
76 ····​close_after·​token_;​76 ····​close_after·​token_;​
77 ····asio:​:​error_code*·​ec_;​77 ····​std:​:​error_code*·​error_;​
78 ····​T*·​t_;​78 ····​T*·​t_;​
79 ··​};​79 ··​};​
80 80
81 ··​/​/​·​The·​async_result·​constructor·​associates·​the·​completion·​handler·​object·​with81 ··​/​/​·​The·​async_result·​constructor·​associates·​the·​completion·​handler·​object·​with
82 ··​/​/​·​the·​result·​of·​the·​initiating·​function.​82 ··​/​/​·​the·​result·​of·​the·​initiating·​function.​
83 ··​explicit·​async_result(completi​on_handler_type&·​h)​83 ··​explicit·​async_result(completi​on_handler_type&·​h)​
84 ····​:​·​timeout_(h.​token_.​timeout_)​,​84 ····​:​·​timeout_(h.​token_.​timeout_)​,​
85 ······​socket_(h.​token_.​socket_)​85 ······​socket_(h.​token_.​socket_)​
86 ··​{86 ··​{
87 ····​h.​ec_·​=·​&ec_;​87 ····​h.​error_·​=·​&error_;​
88 ····​h.​t_·​=·​&t_;​88 ····​h.​t_·​=·​&t_;​
89 ··​}89 ··​}
90 90
91 ··​/​/​·​The·​return_type·​typedef·​determines·​the·​result·​type·​of·​the·​asynchronous91 ··​/​/​·​The·​return_type·​typedef·​determines·​the·​result·​type·​of·​the·​asynchronous
92 ··​/​/​·​operation's·​initiating·​function.​92 ··​/​/​·​operation's·​initiating·​function.​
93 ··​typedef·​T·​return_type;​93 ··​typedef·​T·​return_type;​
94 94
95 ··​/​/​·​The·​get()​·​function·​is·​used·​to·​obtain·​the·​result·​of·​the·​asynchronous95 ··​/​/​·​The·​get()​·​function·​is·​used·​to·​obtain·​the·​result·​of·​the·​asynchronous
96 ··​/​/​·​operation's·​initiating·​function.​·​For·​the·​close_after·​completion·​token,​·​we96 ··​/​/​·​operation's·​initiating·​function.​·​For·​the·​close_after·​completion·​token,​·​we
97 ··​/​/​·​use·​this·​function·​to·​run·​the·​io_context·​until·​the·​operation·​is·​complete.​97 ··​/​/​·​use·​this·​function·​to·​run·​the·​io_context·​until·​the·​operation·​is·​complete.​
98 ··​return_type·​get()​98 ··​return_type·​get()​
99 ··​{99 ··​{
100 ····​asio:​:​io_context&·​io_context·​=·​socket_.​get_executor()​.​context()​;​100 ····​asio:​:​io_context&·​io_context·​=·​socket_.​get_executor()​.​context()​;​
101 101
102 ····​/​/​·​Restart·​the·​io_context,​·​as·​it·​may·​have·​been·​left·​in·​the·​"stopped"·​state102 ····​/​/​·​Restart·​the·​io_context,​·​as·​it·​may·​have·​been·​left·​in·​the·​"stopped"·​state
103 ····​/​/​·​by·​a·​previous·​operation.​103 ····​/​/​·​by·​a·​previous·​operation.​
104 ····​io_context.​restart()​;​104 ····​io_context.​restart()​;​
105 105
106 ····​/​/​·​Block·​until·​the·​asynchronous·​operation·​has·​completed,​·​or·​timed·​out.​·​If106 ····​/​/​·​Block·​until·​the·​asynchronous·​operation·​has·​completed,​·​or·​timed·​out.​·​If
107 ····​/​/​·​the·​pending·​asynchronous·​operation·​is·​a·​composed·​operation,​·​the·​deadline107 ····​/​/​·​the·​pending·​asynchronous·​operation·​is·​a·​composed·​operation,​·​the·​deadline
108 ····​/​/​·​applies·​to·​the·​entire·​operation,​·​rather·​than·​individual·​operations·​on108 ····​/​/​·​applies·​to·​the·​entire·​operation,​·​rather·​than·​individual·​operations·​on
109 ····​/​/​·​the·​socket.​109 ····​/​/​·​the·​socket.​
110 ····​io_context.​run_for(timeout_)​;​110 ····​io_context.​run_for(timeout_)​;​
111 111
112 ····​/​/​·​If·​the·​asynchronous·​operation·​completed·​successfully·​then·​the·​io_context112 ····​/​/​·​If·​the·​asynchronous·​operation·​completed·​successfully·​then·​the·​io_context
113 ····​/​/​·​would·​have·​been·​stopped·​due·​to·​running·​out·​of·​work.​·​If·​it·​was·​not113 ····​/​/​·​would·​have·​been·​stopped·​due·​to·​running·​out·​of·​work.​·​If·​it·​was·​not
114 ····​/​/​·​stopped,​·​then·​the·​io_context:​:​run_for·​call·​must·​have·​timed·​out·​and·​the114 ····​/​/​·​stopped,​·​then·​the·​io_context:​:​run_for·​call·​must·​have·​timed·​out·​and·​the
115 ····​/​/​·​operation·​is·​still·​incomplete.​115 ····​/​/​·​operation·​is·​still·​incomplete.​
116 ····​if·​(!io_context.​stopped()​)​116 ····​if·​(!io_context.​stopped()​)​
117 ····​{117 ····​{
118 ······​/​/​·​Close·​the·​socket·​to·​cancel·​the·​outstanding·​asynchronous·​operation.​118 ······​/​/​·​Close·​the·​socket·​to·​cancel·​the·​outstanding·​asynchronous·​operation.​
119 ······​socket_.​close()​;​119 ······​socket_.​close()​;​
120 120
121 ······​/​/​·​Run·​the·​io_context·​again·​until·​the·​operation·​completes.​121 ······​/​/​·​Run·​the·​io_context·​again·​until·​the·​operation·​completes.​
122 ······​io_context.​run()​;​122 ······​io_context.​run()​;​
123 ····​}123 ····​}
124 124
125 ····​/​/​·​If·​the·​operation·​failed,​·​throw·​an·​exception.​·​Otherwise·​return·​the·​result.​125 ····​/​/​·​If·​the·​operation·​failed,​·​throw·​an·​exception.​·​Otherwise·​return·​the·​result.​
126 ····​return·​ec_·​?·​throw·asio:​:​system_error(ec_)​·​:​·​t_;​126 ····​return·​error_·​?·​throw·​std:​:​system_error(error_)​·​:​·​t_;​
127 ··​}127 ··​}
128 128
129 private:​129 private:​
130 ··asio:​:​chrono:​:​steady_clock:​:​duration·​timeout_;​130 ··​std:​:​chrono:​:​steady_clock:​:​duration·​timeout_;​
131 ··​tcp_socket&·​socket_;​131 ··​tcp_socket&·​socket_;​
132 ··asio:​:​error_code·​ec_;​132 ··​std:​:​error_code·​error_;​
133 ··​T·​t_;​133 ··​T·​t_;​
134 };​134 };​
135 135
136 }·​/​/​·​namespace·​asio136 }·​/​/​·​namespace·​asio
137 137
138 /​/​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​138 /​/​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​
139 139
140 int·​main(int·​argc,​·​char*·​argv[])​140 int·​main(int·​argc,​·​char*·​argv[])​
141 {141 {
142 ··​try142 ··​try
143 ··​{143 ··​{
144 ····​if·​(argc·​!=·​4)​144 ····​if·​(argc·​!=·​4)​
145 ····​{145 ····​{
146 ······​std:​:​cerr·​<<·​"Usage:​·​blocking_tcp_client·​<host>·​<port>·​<message>\n";​146 ······​std:​:​cerr·​<<·​"Usage:​·​blocking_tcp_client·​<host>·​<port>·​<message>\n";​
147 ······​return·​1;​147 ······​return·​1;​
148 ····​}148 ····​}
149 149
150 ····​asio:​:​io_context·​io_context;​150 ····​asio:​:​io_context·​io_context;​
151 151
152 ····​/​/​·​Resolve·​the·​host·​name·​and·​service·​to·​a·​list·​of·​endpoints.​152 ····​/​/​·​Resolve·​the·​host·​name·​and·​service·​to·​a·​list·​of·​endpoints.​
153 ····​tcp:​:​resolver:​:​results_type·endpoints·=153 ····auto·endpoints·=·​tcp:​:​resolver(io_context)​.​resolve(argv[1],​·argv[2])​;​
154 ······tcp:​:​resolver(io_context)​.​resolve(argv[1],​·argv[2])​;​
155 154
156 ····​tcp_socket·​socket(io_context)​;​155 ····​tcp_socket·​socket(io_context)​;​
157 156
158 ····​/​/​·​Run·​an·​asynchronous·​connect·​operation·​with·​a·​timeout.​157 ····​/​/​·​Run·​an·​asynchronous·​connect·​operation·​with·​a·​timeout.​
159 ····​asio:​:​async_connect(socket,​·​endpoints,​158 ····​asio:​:​async_connect(socket,​·​endpoints,​
160 ········​close_after(asio:​:​chrono:​:​seconds(10)​,​·​socket)​)​;​159 ········​close_after(std:​:​chrono:​:​seconds(10)​,​·​socket)​)​;​
161 160
162 ····​asio:​:​chrono:​:​steady_clock:​:​time_point·time_sent·=161 ····​auto·time_sent·=·std:​:​chrono:​:​steady_clock:​:​now()​;​
163 ······asio:​:​chrono:​:​steady_clock:​:​now()​;​
164 162
165 ····​/​/​·​Run·​an·​asynchronous·​write·​operation·​with·​a·​timeout.​163 ····​/​/​·​Run·​an·​asynchronous·​write·​operation·​with·​a·​timeout.​
166 ····​std:​:​string·​msg·​=·​argv[3]·​+·​std:​:​string("\n")​;​164 ····​std:​:​string·​msg·​=·​argv[3]·​+·​std:​:​string("\n")​;​
167 ····​asio:​:​async_write(socket,​·​asio:​:​buffer(msg)​,​165 ····​asio:​:​async_write(socket,​·​asio:​:​buffer(msg)​,​
168 ········​close_after(asio:​:​chrono:​:​seconds(10)​,​·​socket)​)​;​166 ········​close_after(std:​:​chrono:​:​seconds(10)​,​·​socket)​)​;​
169 167
170 ····​for·​(std:​:​string·​input_buffer;​;​)​168 ····​for·​(std:​:​string·​input_buffer;​;​)​
171 ····​{169 ····​{
172 ······​/​/​·​Run·​an·​asynchronous·​read·​operation·​with·​a·​timeout.​170 ······​/​/​·​Run·​an·​asynchronous·​read·​operation·​with·​a·​timeout.​
173 ······​std:​:​size_t·​n·​=·​asio:​:​async_read_until(sock​et,​171 ······​std:​:​size_t·​n·​=·​asio:​:​async_read_until(sock​et,​
174 ··········​asio:​:​dynamic_buffer(input_​buffer)​,​·​'\n',​172 ··········​asio:​:​dynamic_buffer(input_​buffer)​,​·​'\n',​
175 ··········​close_after(asio:​:​chrono:​:​seconds(10)​,​·​socket)​)​;​173 ··········​close_after(std:​:​chrono:​:​seconds(10)​,​·​socket)​)​;​
176 174
177 ······​std:​:​string·​line(input_buffer.​substr(0,​·​n·​-​·​1)​)​;​175 ······​std:​:​string·​line(input_buffer.​substr(0,​·​n·​-​·​1)​)​;​
178 ······​input_buffer.​erase(0,​·​n)​;​176 ······​input_buffer.​erase(0,​·​n)​;​
179 177
180 ······​/​/​·​Keep·​going·​until·​we·​get·​back·​the·​line·​that·​was·​sent.​178 ······​/​/​·​Keep·​going·​until·​we·​get·​back·​the·​line·​that·​was·​sent.​
181 ······​if·​(line·​==·​argv[3])​179 ······​if·​(line·​==·​argv[3])​
182 ········​break;​180 ········​break;​
183 ····​}181 ····​}
184 182
185 ····​asio:​:​chrono:​:​steady_clock:​:​time_point·time_received·=183 ····​auto·time_received·=·std:​:​chrono:​:​steady_clock:​:​now()​;​
186 ······asio:​:​chrono:​:​steady_clock:​:​now()​;​
187 184
188 ····​std:​:​cout·​<<·​"Round·​trip·​time:​·​";​185 ····​std:​:​cout·​<<·​"Round·​trip·​time:​·​";​
189 ····​std:​:​cout·​<<·asio:​:​chrono:​:​duration_cast<186 ····​std:​:​cout·​<<·​std:​:​chrono:​:​duration_cast<
190 ······asio:​:​chrono:​:​microseconds>(187 ······​std:​:​chrono:​:​microseconds>(
191 ········​time_received·​-​·​time_sent)​.​count()​;​188 ········​time_received·​-​·​time_sent)​.​count()​;​
192 ····​std:​:​cout·​<<·​"·​microseconds\n";​189 ····​std:​:​cout·​<<·​"·​microseconds\n";​
193 ··​}190 ··​}
194 ··​catch·​(std:​:​exception&·​e)​191 ··​catch·​(std:​:​exception&·​e)​
195 ··​{192 ··​{
196 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​193 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​
197 ··​}194 ··​}
198 195
199 ··​return·​0;​196 ··​return·​0;​
200 }197 }