src/​examples/​cpp03/​timeouts/​blocking_tcp_client.​cppsrc/​examples/​cpp11/​timeouts/​blocking_tcp_client.​cpp
1 /​/​1 /​/​
2 /​/​·​blocking_tcp_client.​cpp2 /​/​·​blocking_tcp_client.​cpp
3 /​/​·​~~~~~~~~~~~~~~~~~~~~~​~~3 /​/​·​~~~~~~~~~~~~~~~~~~~~~​~~
4 /​/​4 /​/​
5 /​/​·​Copyright·​(c)​·​2003-​2023·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2023·​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/​connect.​hpp"12 #include·​"asio/​connect.​hpp"
13 #include·​"asio/​io_context.​hpp"13 #include·​"asio/​io_context.​hpp"
14 #include·​"asio/​ip/​tcp.​hpp"14 #include·​"asio/​ip/​tcp.​hpp"
15 #include·​"asio/​read_until.​hpp"15 #include·​"asio/​read_until.​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·​<string>20 #include·​<string>
21 #include·​<boost/​lambda/​bind.​hpp>
22 #include·​<boost/​lambda/​lambda.​hpp>
23 21
24 using·​asio:​:​ip:​:​tcp;​22 using·​asio:​:​ip:​:​tcp;​
25 using·​boost:​:​lambda:​:​bind;​
26 using·​boost:​:​lambda:​:​var;​
27 using·​boost:​:​lambda:​:​_1;​
28 using·​boost:​:​lambda:​:​_2;​
29 23
30 /​/​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​24 /​/​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​
31 25
32 /​/​26 /​/​
33 /​/​·​This·​class·​manages·​socket·​timeouts·​by·​running·​the·​io_context·​using·​the·​timed27 /​/​·​This·​class·​manages·​socket·​timeouts·​by·​running·​the·​io_context·​using·​the·​timed
34 /​/​·​io_context:​:​run_for()​·​member·​function.​·​Each·​asynchronous·​operation·​is·​given28 /​/​·​io_context:​:​run_for()​·​member·​function.​·​Each·​asynchronous·​operation·​is·​given
35 /​/​·​a·​timeout·​within·​which·​it·​must·​complete.​·​The·​socket·​operations·​themselves29 /​/​·​a·​timeout·​within·​which·​it·​must·​complete.​·​The·​socket·​operations·​themselves
36 /​/​·​use·boost:​:​lambda·function·objects·​as·​completion·​handlers.​·​For·​a·​given30 /​/​·​use·​lambdas·​as·​completion·​handlers.​·​For·​a·​given·socket·operation,​·the·client
37 /​/​·socket·operation,​·​the·​client·​object·runs·the·io_context·​to·block·thread31 /​/​·​object·​runs·​the·io_context·to·block·thread·execution·until·​the·operation
38 /​/​·execution·until·​the·operation·completes·or·​the·timeout·is·reached.​·If·the32 /​/​·​completes·or·​the·timeout·is·reached.​·If·​the·io_context:​:​run_for()​·function
39 /​/​·​io_context:​:​run_for()​·function·​times·​out,​·the·​socket·is·closed·and·the33 /​/​·times·out,​·the·socket·is·closed·and·​the·​outstanding·asynchronous·​operation
40 /​/​·outstanding·asynchronous·operation·​is·​cancelled.​34 /​/​·​is·​cancelled.​
41 /​/​35 /​/​
42 class·​client36 class·​client
43 {37 {
44 public:​38 public:​
45 ··​client()​
46 ····​:​·​socket_(io_context_)​
47 ··​{
48 ··​}
49
50 ··​void·​connect(const·​std:​:​string&·​host,​·​const·​std:​:​string&·​service,​39 ··​void·​connect(const·​std:​:​string&·​host,​·​const·​std:​:​string&·​service,​
51 ······asio:​:​chrono:​:​steady_clock:​:​duration·​timeout)​40 ······​std:​:​chrono:​:​steady_clock:​:​duration·​timeout)​
52 ··​{41 ··​{
53 ····​/​/​·​Resolve·​the·​host·​name·​and·​service·​to·​a·​list·​of·​endpoints.​42 ····​/​/​·​Resolve·​the·​host·​name·​and·​service·​to·​a·​list·​of·​endpoints.​
54 ····​tcp:​:​resolver:​:​results_type·endpoints·=43 ····auto·endpoints·=·​tcp:​:​resolver(io_context_)​.​resolve(host,​·service)​;​
55 ······tcp:​:​resolver(io_context_)​.​resolve(host,​·service)​;​
56 44
57 ····​/​/​·​Start·​the·​asynchronous·​operation·​itself.​·​The·boost:​:​lambda·function45 ····​/​/​·​Start·​the·​asynchronous·​operation·​itself.​·​The·lambda·that·is·used·as·a
58 ····​/​/​·object·is·used·as·a·​callback·and·​will·​update·​the·​ec·​variable·​when·​the46 ····​/​/​·​callback·​will·​update·​the·​error·​variable·​when·​the·operation·completes.​
59 ····​/​/​·operation·completes.​·​The·​blocking_udp_client.​cpp·​example·​shows·​how·​you47 ····​/​/​·​The·​blocking_udp_client.​cpp·​example·​shows·​how·​you·can·use·std:​:​bind
60 ····​/​/​·can·use·boost:​:​bind·​rather·​than·boost:​:​lambda.​48 ····​/​/​·​rather·​than·a·lambda.​
61 ····asio:​:​error_code·​ec;​49 ····​std:​:​error_code·​error;​
62 ····​asio:​:​async_connect(socket_​,​·​endpoints,​·var(ec)​·=·_1)​;​50 ····​asio:​:​async_connect(socket_​,​·​endpoints,​
51 ········​[&](const·​std:​:​error_code&·​result_error,​
52 ············​const·​tcp:​:​endpoint&·​/​*result_endpoint*/​)​
53 ········​{
54 ··········​error·​=·​result_error;​
55 ········​})​;​
63 56
64 ····​/​/​·​Run·​the·​operation·​until·​it·​completes,​·​or·​until·​the·​timeout.​57 ····​/​/​·​Run·​the·​operation·​until·​it·​completes,​·​or·​until·​the·​timeout.​
65 ····​run(timeout)​;​58 ····​run(timeout)​;​
66 59
67 ····​/​/​·​Determine·​whether·​a·​connection·​was·​successfully·​established.​60 ····​/​/​·​Determine·​whether·​a·​connection·​was·​successfully·​established.​
68 ····​if·​(ec)​61 ····​if·​(error)​
69 ······​throw·asio:​:​system_error(ec)​;​62 ······​throw·​std:​:​system_error(error)​;​
70 ··​}63 ··​}
71 64
72 ··​std:​:​string·​read_line(asio:​:​chrono:​:​steady_clock:​:​duration·​timeout)​65 ··​std:​:​string·​read_line(std:​:​chrono:​:​steady_clock:​:​duration·​timeout)​
73 ··​{66 ··​{
74 ····​/​/​·​Start·​the·​asynchronous·​operation.​·​The·boost:​:​lambda·function·object·is67 ····​/​/​·​Start·​the·​asynchronous·​operation.​·​The·lambda·that·is·​used·as·a·callback
75 ····​/​/​·used·as·a·callback·and·​will·​update·​the·​ec·​variable·​when·​the·​operation68 ····​/​/​·​will·​update·​the·​error·and·n·​variables·​when·​the·​operation·completes.​·The
76 ····​/​/​·completes.​·The·​blocking_udp_client.​cpp·​example·​shows·​how·​you·​can·​use69 ····​/​/​·​blocking_udp_client.​cpp·​example·​shows·​how·​you·​can·​use·std:​:​bind·rather
77 ····​/​/​·boost:​:​bind·rather·​than·boost:​:​lambda.​70 ····​/​/​·​than·a·lambda.​
78 ····asio:​:​error_code·​ec;​71 ····​std:​:​error_code·​error;​
79 ····​std:​:​size_t·​n·​=·​0;​72 ····​std:​:​size_t·​n·​=·​0;​
80 ····​asio:​:​async_read_until(sock​et_,​73 ····​asio:​:​async_read_until(sock​et_,​
81 ········​asio:​:​dynamic_buffer(input_​buffer_)​,​74 ········​asio:​:​dynamic_buffer(input_​buffer_)​,​·'\n',​
82 ········'\n',​·(var(ec)​·=·_1,​·var(n)​·=·_2)​)​;​75 ········[&](const·std:​:​error_code&·result_error,​
76 ············​std:​:​size_t·​result_n)​
77 ········​{
78 ··········​error·​=·​result_error;​
79 ··········​n·​=·​result_n;​
80 ········​})​;​
83 81
84 ····​/​/​·​Run·​the·​operation·​until·​it·​completes,​·​or·​until·​the·​timeout.​82 ····​/​/​·​Run·​the·​operation·​until·​it·​completes,​·​or·​until·​the·​timeout.​
85 ····​run(timeout)​;​83 ····​run(timeout)​;​
86 84
87 ····​/​/​·​Determine·​whether·​the·​read·​completed·​successfully.​85 ····​/​/​·​Determine·​whether·​the·​read·​completed·​successfully.​
88 ····​if·​(ec)​86 ····​if·​(error)​
89 ······​throw·asio:​:​system_error(ec)​;​87 ······​throw·​std:​:​system_error(error)​;​
90 88
91 ····​std:​:​string·​line(input_buffer_.​substr(0,​·​n·​-​·​1)​)​;​89 ····​std:​:​string·​line(input_buffer_.​substr(0,​·​n·​-​·​1)​)​;​
92 ····​input_buffer_.​erase(0,​·​n)​;​90 ····​input_buffer_.​erase(0,​·​n)​;​
93 ····​return·​line;​91 ····​return·​line;​
94 ··​}92 ··​}
95 93
96 ··​void·​write_line(const·​std:​:​string&·​line,​94 ··​void·​write_line(const·​std:​:​string&·​line,​
97 ······asio:​:​chrono:​:​steady_clock:​:​duration·​timeout)​95 ······​std:​:​chrono:​:​steady_clock:​:​duration·​timeout)​
98 ··​{96 ··​{
99 ····​std:​:​string·​data·​=·​line·​+·​"\n";​97 ····​std:​:​string·​data·​=·​line·​+·​"\n";​
100 98
101 ····​/​/​·​Start·​the·​asynchronous·​operation.​·The·boost:​:​lambda·function·object·is99 ····​/​/​·​Start·​the·​asynchronous·​operation·itself.​·The·lambda·that·is·used·as·a
102 ····​/​/​·used·as·a·​callback·and·​will·​update·​the·​ec·​variable·​when·​the·​operation100 ····​/​/​·​callback·​will·​update·​the·​error·​variable·​when·​the·​operation·completes.​
103 ····​/​/​·completes.​·​The·​blocking_udp_client.​cpp·​example·​shows·​how·​you·​can·​use101 ····​/​/​·​The·​blocking_udp_client.​cpp·​example·​shows·​how·​you·​can·​use·std:​:​bind
104 ····​/​/​·boost:​:​bind·​rather·​than·boost:​:​lambda.​102 ····​/​/​·​rather·​than·a·lambda.​
105 ····asio:​:​error_code·​ec;​103 ····​std:​:​error_code·​error;​
106 ····​asio:​:​async_write(socket_,​·​asio:​:​buffer(data)​,​·var(ec)​·=·_1)​;​104 ····​asio:​:​async_write(socket_,​·​asio:​:​buffer(data)​,​
105 ········​[&](const·​std:​:​error_code&·​result_error,​
106 ············​std:​:​size_t·​/​*result_n*/​)​
107 ········​{
108 ··········​error·​=·​result_error;​
109 ········​})​;​
107 110
108 ····​/​/​·​Run·​the·​operation·​until·​it·​completes,​·​or·​until·​the·​timeout.​111 ····​/​/​·​Run·​the·​operation·​until·​it·​completes,​·​or·​until·​the·​timeout.​
109 ····​run(timeout)​;​112 ····​run(timeout)​;​
110 113
111 ····​/​/​·​Determine·​whether·​the·​read·​completed·​successfully.​114 ····​/​/​·​Determine·​whether·​the·​read·​completed·​successfully.​
112 ····​if·​(ec)​115 ····​if·​(error)​
113 ······​throw·asio:​:​system_error(ec)​;​116 ······​throw·​std:​:​system_error(error)​;​
114 ··​}117 ··​}
115 118
116 private:​119 private:​
117 ··​void·​run(asio:​:​chrono:​:​steady_clock:​:​duration·​timeout)​120 ··​void·​run(std:​:​chrono:​:​steady_clock:​:​duration·​timeout)​
118 ··​{121 ··​{
119 ····​/​/​·​Restart·​the·​io_context,​·​as·​it·​may·​have·​been·​left·​in·​the·​"stopped"·​state122 ····​/​/​·​Restart·​the·​io_context,​·​as·​it·​may·​have·​been·​left·​in·​the·​"stopped"·​state
120 ····​/​/​·​by·​a·​previous·​operation.​123 ····​/​/​·​by·​a·​previous·​operation.​
121 ····​io_context_.​restart()​;​124 ····​io_context_.​restart()​;​
122 125
123 ····​/​/​·​Block·​until·​the·​asynchronous·​operation·​has·​completed,​·​or·​timed·​out.​·​If126 ····​/​/​·​Block·​until·​the·​asynchronous·​operation·​has·​completed,​·​or·​timed·​out.​·​If
124 ····​/​/​·​the·​pending·​asynchronous·​operation·​is·​a·​composed·​operation,​·​the·​deadline127 ····​/​/​·​the·​pending·​asynchronous·​operation·​is·​a·​composed·​operation,​·​the·​deadline
125 ····​/​/​·​applies·​to·​the·​entire·​operation,​·​rather·​than·​individual·​operations·​on128 ····​/​/​·​applies·​to·​the·​entire·​operation,​·​rather·​than·​individual·​operations·​on
126 ····​/​/​·​the·​socket.​129 ····​/​/​·​the·​socket.​
127 ····​io_context_.​run_for(timeout)​;​130 ····​io_context_.​run_for(timeout)​;​
128 131
129 ····​/​/​·​If·​the·​asynchronous·​operation·​completed·​successfully·​then·​the·​io_context132 ····​/​/​·​If·​the·​asynchronous·​operation·​completed·​successfully·​then·​the·​io_context
130 ····​/​/​·​would·​have·​been·​stopped·​due·​to·​running·​out·​of·​work.​·​If·​it·​was·​not133 ····​/​/​·​would·​have·​been·​stopped·​due·​to·​running·​out·​of·​work.​·​If·​it·​was·​not
131 ····​/​/​·​stopped,​·​then·​the·​io_context:​:​run_for·​call·​must·​have·​timed·​out.​134 ····​/​/​·​stopped,​·​then·​the·​io_context:​:​run_for·​call·​must·​have·​timed·​out.​
132 ····​if·​(!io_context_.​stopped()​)​135 ····​if·​(!io_context_.​stopped()​)​
133 ····​{136 ····​{
134 ······​/​/​·​Close·​the·​socket·​to·​cancel·​the·​outstanding·​asynchronous·​operation.​137 ······​/​/​·​Close·​the·​socket·​to·​cancel·​the·​outstanding·​asynchronous·​operation.​
135 ······​socket_.​close()​;​138 ······​socket_.​close()​;​
136 139
137 ······​/​/​·​Run·​the·​io_context·​again·​until·​the·​operation·​completes.​140 ······​/​/​·​Run·​the·​io_context·​again·​until·​the·​operation·​completes.​
138 ······​io_context_.​run()​;​141 ······​io_context_.​run()​;​
139 ····​}142 ····​}
140 ··​}143 ··​}
141 144
142 ··​asio:​:​io_context·​io_context_;​145 ··​asio:​:​io_context·​io_context_;​
143 ··​tcp:​:​socket·​socket_;​146 ··​tcp:​:​socket·​socket_{io_context_};​
144 ··​std:​:​string·​input_buffer_;​147 ··​std:​:​string·​input_buffer_;​
145 };​148 };​
146 149
147 /​/​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​150 /​/​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​-​
148 151
149 int·​main(int·​argc,​·​char*·​argv[])​152 int·​main(int·​argc,​·​char*·​argv[])​
150 {153 {
151 ··​try154 ··​try
152 ··​{155 ··​{
153 ····​if·​(argc·​!=·​4)​156 ····​if·​(argc·​!=·​4)​
154 ····​{157 ····​{
155 ······​std:​:​cerr·​<<·​"Usage:​·​blocking_tcp_client·​<host>·​<port>·​<message>\n";​158 ······​std:​:​cerr·​<<·​"Usage:​·​blocking_tcp_client·​<host>·​<port>·​<message>\n";​
156 ······​return·​1;​159 ······​return·​1;​
157 ····​}160 ····​}
158 161
159 ····​client·​c;​162 ····​client·​c;​
160 ····​c.​connect(argv[1],​·​argv[2],​·asio:​:​chrono:​:​seconds(10)​)​;​163 ····​c.​connect(argv[1],​·​argv[2],​·​std:​:​chrono:​:​seconds(10)​)​;​
161 164
162 ····​asio:​:​chrono:​:​steady_clock:​:​time_point·time_sent·=165 ····​auto·time_sent·=·std:​:​chrono:​:​steady_clock:​:​now()​;​
163 ······asio:​:​chrono:​:​steady_clock:​:​now()​;​
164 166
165 ····​c.​write_line(argv[3],​·asio:​:​chrono:​:​seconds(10)​)​;​167 ····​c.​write_line(argv[3],​·​std:​:​chrono:​:​seconds(10)​)​;​
166 168
167 ····​for·​(;​;​)​169 ····​for·​(;​;​)​
168 ····​{170 ····​{
169 ······​std:​:​string·​line·​=·​c.​read_line(asio:​:​chrono:​:​seconds(10)​)​;​171 ······​std:​:​string·​line·​=·​c.​read_line(std:​:​chrono:​:​seconds(10)​)​;​
170 172
171 ······​/​/​·​Keep·​going·​until·​we·​get·​back·​the·​line·​that·​was·​sent.​173 ······​/​/​·​Keep·​going·​until·​we·​get·​back·​the·​line·​that·​was·​sent.​
172 ······​if·​(line·​==·​argv[3])​174 ······​if·​(line·​==·​argv[3])​
173 ········​break;​175 ········​break;​
174 ····​}176 ····​}
175 177
176 ····​asio:​:​chrono:​:​steady_clock:​:​time_point·time_received·=178 ····​auto·time_received·=·std:​:​chrono:​:​steady_clock:​:​now()​;​
177 ······asio:​:​chrono:​:​steady_clock:​:​now()​;​
178 179
179 ····​std:​:​cout·​<<·​"Round·​trip·​time:​·​";​180 ····​std:​:​cout·​<<·​"Round·​trip·​time:​·​";​
180 ····​std:​:​cout·​<<·asio:​:​chrono:​:​duration_cast<181 ····​std:​:​cout·​<<·​std:​:​chrono:​:​duration_cast<
181 ······asio:​:​chrono:​:​microseconds>(182 ······​std:​:​chrono:​:​microseconds>(
182 ········​time_received·​-​·​time_sent)​.​count()​;​183 ········​time_received·​-​·​time_sent)​.​count()​;​
183 ····​std:​:​cout·​<<·​"·​microseconds\n";​184 ····​std:​:​cout·​<<·​"·​microseconds\n";​
184 ··​}185 ··​}
185 ··​catch·​(std:​:​exception&·​e)​186 ··​catch·​(std:​:​exception&·​e)​
186 ··​{187 ··​{
187 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​188 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​
188 ··​}189 ··​}
189 190
190 ··​return·​0;​191 ··​return·​0;​
191 }192 }