src/examples/cpp03/timeouts/async_tcp_client.cpp | src/examples/cpp11/timeouts/async_tcp_client.cpp |
⋮ | ⋮ |
1 | // | 1 | // |
2 | //·async_tcp_client.cpp | 2 | //·async_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·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/tcp.hpp" | 13 | #include·"asio/ip/tcp.hpp" |
14 | #include·"asio/read_until.hpp" | 14 | #include·"asio/read_until.hpp" |
15 | #include·"asio/steady_timer.hpp" | 15 | #include·"asio/steady_timer.hpp" |
16 | #include·"asio/write.hpp" | 16 | #include·"asio/write.hpp" |
17 | #include·<boost/bind/bind.hpp> | 17 | #include·<functional> |
18 | #include·<iostream> | 18 | #include·<iostream> |
19 | #include·<string> | 19 | #include·<string> |
20 | | 20 | |
21 | using·asio::steady_timer; | 21 | using·asio::steady_timer; |
22 | using·asio::ip::tcp; | 22 | using·asio::ip::tcp; |
| 23 | using·std::placeholders::_1; |
| 24 | using·std::placeholders::_2; |
23 | | 25 | |
24 | // | 26 | // |
25 | //·This·class·manages·socket·timeouts·by·applying·the·concept·of·a·deadline. | 27 | //·This·class·manages·socket·timeouts·by·applying·the·concept·of·a·deadline. |
26 | //·Some·asynchronous·operations·are·given·deadlines·by·which·they·must·complete. | 28 | //·Some·asynchronous·operations·are·given·deadlines·by·which·they·must·complete. |
27 | //·Deadlines·are·enforced·by·an·"actor"·that·persists·for·the·lifetime·of·the | 29 | //·Deadlines·are·enforced·by·an·"actor"·that·persists·for·the·lifetime·of·the |
28 | //·client·object: | 30 | //·client·object: |
29 | // | 31 | // |
30 | //··+----------------+ | 32 | //··+----------------+ |
31 | //··|················| | 33 | //··|················| |
32 | //··|·check_deadline·|<---+ | 34 | //··|·check_deadline·|<---+ |
33 | //··|················|····| | 35 | //··|················|····| |
34 | //··+----------------+····|·async_wait() | 36 | //··+----------------+····|·async_wait() |
35 | //··············|·········| | 37 | //··············|·········| |
36 | //··············+---------+ | 38 | //··············+---------+ |
37 | // | 39 | // |
38 | //·If·the·deadline·actor·determines·that·the·deadline·has·expired,·the·socket | 40 | //·If·the·deadline·actor·determines·that·the·deadline·has·expired,·the·socket |
39 | //·is·closed·and·any·outstanding·operations·are·consequently·cancelled. | 41 | //·is·closed·and·any·outstanding·operations·are·consequently·cancelled. |
40 | // | 42 | // |
41 | //·Connection·establishment·involves·trying·each·endpoint·in·turn·until·a | 43 | //·Connection·establishment·involves·trying·each·endpoint·in·turn·until·a |
42 | //·connection·is·successful,·or·the·available·endpoints·are·exhausted.·If·the | 44 | //·connection·is·successful,·or·the·available·endpoints·are·exhausted.·If·the |
43 | //·deadline·actor·closes·the·socket,·the·connect·actor·is·woken·up·and·moves·to | 45 | //·deadline·actor·closes·the·socket,·the·connect·actor·is·woken·up·and·moves·to |
44 | //·the·next·endpoint. | 46 | //·the·next·endpoint. |
45 | // | 47 | // |
46 | //··+---------------+ | 48 | //··+---------------+ |
47 | //··|···············| | 49 | //··|···············| |
48 | //··|·start_connect·|<---+ | 50 | //··|·start_connect·|<---+ |
49 | //··|···············|····| | 51 | //··|···············|····| |
50 | //··+---------------+····| | 52 | //··+---------------+····| |
51 | //···········|···········| | 53 | //···········|···········| |
52 | //··async_-··|····+----------------+ | 54 | //··async_-··|····+----------------+ |
53 | //·connect()·|····|················| | 55 | //·connect()·|····|················| |
54 | //···········+--->|·handle_connect·| | 56 | //···········+--->|·handle_connect·| |
55 | //················|················| | 57 | //················|················| |
56 | //················+----------------+ | 58 | //················+----------------+ |
57 | //··························: | 59 | //··························: |
58 | //·Once·a·connection·is·····: | 60 | //·Once·a·connection·is·····: |
59 | //·made,·the·connect········: | 61 | //·made,·the·connect········: |
60 | //·actor·forks·in·two·-·····: | 62 | //·actor·forks·in·two·-·····: |
61 | //··························: | 63 | //··························: |
62 | //·an·actor·for·reading·····:·······and·an·actor·for | 64 | //·an·actor·for·reading·····:·······and·an·actor·for |
63 | //·inbound·messages:········:·······sending·heartbeats: | 65 | //·inbound·messages:········:·······sending·heartbeats: |
64 | //··························: | 66 | //··························: |
65 | //··+------------+··········:··········+-------------+ | 67 | //··+------------+··········:··········+-------------+ |
66 | //··|············|<-·-·-·-·-+-·-·-·-·->|·············| | 68 | //··|············|<-·-·-·-·-+-·-·-·-·->|·············| |
67 | //··|·start_read·|·····················|·start_write·|<---+ | 69 | //··|·start_read·|·····················|·start_write·|<---+ |
68 | //··|············|<---+················|·············|····| | 70 | //··|············|<---+················|·············|····| |
69 | //··+------------+····|················+-------------+····|·async_wait() | 71 | //··+------------+····|················+-------------+····|·async_wait() |
70 | //··········|·········|························|··········| | 72 | //··········|·········|························|··········| |
71 | //··async_-·|····+-------------+·······async_-·|····+--------------+ | 73 | //··async_-·|····+-------------+·······async_-·|····+--------------+ |
72 | //···read_-·|····|·············|·······write()·|····|··············| | 74 | //···read_-·|····|·············|·······write()·|····|··············| |
73 | //··until()·+--->|·handle_read·|···············+--->|·handle_write·| | 75 | //··until()·+--->|·handle_read·|···············+--->|·handle_write·| |
74 | //···············|·············|····················|··············| | 76 | //···············|·············|····················|··············| |
75 | //···············+-------------+····················+--------------+ | 77 | //···············+-------------+····················+--------------+ |
76 | // | 78 | // |
77 | //·The·input·actor·reads·messages·from·the·socket,·where·messages·are·delimited | 79 | //·The·input·actor·reads·messages·from·the·socket,·where·messages·are·delimited |
78 | //·by·the·newline·character.·The·deadline·for·a·complete·message·is·30·seconds. | 80 | //·by·the·newline·character.·The·deadline·for·a·complete·message·is·30·seconds. |
79 | // | 81 | // |
80 | //·The·heartbeat·actor·sends·a·heartbeat·(a·message·that·consists·of·a·single | 82 | //·The·heartbeat·actor·sends·a·heartbeat·(a·message·that·consists·of·a·single |
81 | //·newline·character)·every·10·seconds.·In·this·example,·no·deadline·is·applied | 83 | //·newline·character)·every·10·seconds.·In·this·example,·no·deadline·is·applied |
82 | //·to·message·sending. | 84 | //·to·message·sending. |
83 | // | 85 | // |
84 | class·client | 86 | class·client |
85 | { | 87 | { |
86 | public: | 88 | public: |
87 | ··client(asio::io_context&·io_context) | 89 | ··client(asio::io_context&·io_context) |
88 | ····:·stopped_(false), | 90 | ····:·socket_(io_context), |
89 | ······socket_(io_context), | |
90 | ······deadline_(io_context), | 91 | ······deadline_(io_context), |
91 | ······heartbeat_timer_(io_context) | 92 | ······heartbeat_timer_(io_context) |
92 | ··{ | 93 | ··{ |
93 | ··} | 94 | ··} |
94 | | 95 | |
95 | ··//·Called·by·the·user·of·the·client·class·to·initiate·the·connection·process. | 96 | ··//·Called·by·the·user·of·the·client·class·to·initiate·the·connection·process. |
96 | ··//·The·endpoints·will·have·been·obtained·using·a·tcp::resolver. | 97 | ··//·The·endpoints·will·have·been·obtained·using·a·tcp::resolver. |
97 | ··void·start(tcp::resolver::results_type·endpoints) | 98 | ··void·start(tcp::resolver::results_type·endpoints) |
98 | ··{ | 99 | ··{ |
99 | ····//·Start·the·connect·actor. | 100 | ····//·Start·the·connect·actor. |
100 | ····endpoints_·=·endpoints; | 101 | ····endpoints_·=·endpoints; |
101 | ····start_connect(endpoints_.begin()); | 102 | ····start_connect(endpoints_.begin()); |
102 | | 103 | |
103 | ····//·Start·the·deadline·actor.·You·will·note·that·we're·not·setting·any | 104 | ····//·Start·the·deadline·actor.·You·will·note·that·we're·not·setting·any |
104 | ····//·particular·deadline·here.·Instead,·the·connect·and·input·actors·will | 105 | ····//·particular·deadline·here.·Instead,·the·connect·and·input·actors·will |
105 | ····//·update·the·deadline·prior·to·each·asynchronous·operation. | 106 | ····//·update·the·deadline·prior·to·each·asynchronous·operation. |
106 | ····deadline_.async_wait(boost::bind(&client::check_deadline,·this)); | 107 | ····deadline_.async_wait(std::bind(&client::check_deadline,·this)); |
107 | ··} | 108 | ··} |
108 | | 109 | |
109 | ··//·This·function·terminates·all·the·actors·to·shut·down·the·connection.·It | 110 | ··//·This·function·terminates·all·the·actors·to·shut·down·the·connection.·It |
110 | ··//·may·be·called·by·the·user·of·the·client·class,·or·by·the·class·itself·in | 111 | ··//·may·be·called·by·the·user·of·the·client·class,·or·by·the·class·itself·in |
111 | ··//·response·to·graceful·termination·or·an·unrecoverable·error. | 112 | ··//·response·to·graceful·termination·or·an·unrecoverable·error. |
112 | ··void·stop() | 113 | ··void·stop() |
113 | ··{ | 114 | ··{ |
114 | ····stopped_·=·true; | 115 | ····stopped_·=·true; |
115 | ····asio::error_code·ignored_ec; | 116 | ····std::error_code·ignored_error; |
116 | ····socket_.close(ignored_ec); | 117 | ····socket_.close(ignored_error); |
117 | ····deadline_.cancel(); | 118 | ····deadline_.cancel(); |
118 | ····heartbeat_timer_.cancel(); | 119 | ····heartbeat_timer_.cancel(); |
119 | ··} | 120 | ··} |
120 | | 121 | |
121 | private: | 122 | private: |
122 | ··void·start_connect(tcp::resolver::results_type::iterator·endpoint_iter) | 123 | ··void·start_connect(tcp::resolver::results_type::iterator·endpoint_iter) |
123 | ··{ | 124 | ··{ |
124 | ····if·(endpoint_iter·!=·endpoints_.end()) | 125 | ····if·(endpoint_iter·!=·endpoints_.end()) |
125 | ····{ | 126 | ····{ |
126 | ······std::cout·<<·"Trying·"·<<·endpoint_iter->endpoint()·<<·"...\n"; | 127 | ······std::cout·<<·"Trying·"·<<·endpoint_iter->endpoint()·<<·"...\n"; |
127 | | 128 | |
128 | ······//·Set·a·deadline·for·the·connect·operation. | 129 | ······//·Set·a·deadline·for·the·connect·operation. |
129 | ······deadline_.expires_after(asio::chrono::seconds(60)); | 130 | ······deadline_.expires_after(std::chrono::seconds(60)); |
130 | | 131 | |
131 | ······//·Start·the·asynchronous·connect·operation. | 132 | ······//·Start·the·asynchronous·connect·operation. |
132 | ······socket_.async_connect(endpoint_iter->endpoint(), | 133 | ······socket_.async_connect(endpoint_iter->endpoint(), |
133 | ··········boost::bind(&client::handle_connect,·this, | 134 | ··········std::bind(&client::handle_connect, |
134 | ············boost::placeholders::_1,·endpoint_iter)); | 135 | ············this,·_1,·endpoint_iter)); |
135 | ····} | 136 | ····} |
136 | ····else | 137 | ····else |
137 | ····{ | 138 | ····{ |
138 | ······//·There·are·no·more·endpoints·to·try.·Shut·down·the·client. | 139 | ······//·There·are·no·more·endpoints·to·try.·Shut·down·the·client. |
139 | ······stop(); | 140 | ······stop(); |
140 | ····} | 141 | ····} |
141 | ··} | 142 | ··} |
142 | | 143 | |
143 | ··void·handle_connect(const·asio::error_code&·ec, | 144 | ··void·handle_connect(const·std::error_code&·error, |
144 | ······tcp::resolver::results_type::iterator·endpoint_iter) | 145 | ······tcp::resolver::results_type::iterator·endpoint_iter) |
145 | ··{ | 146 | ··{ |
146 | ····if·(stopped_) | 147 | ····if·(stopped_) |
147 | ······return; | 148 | ······return; |
148 | | 149 | |
149 | ····//·The·async_connect()·function·automatically·opens·the·socket·at·the·start | 150 | ····//·The·async_connect()·function·automatically·opens·the·socket·at·the·start |
150 | ····//·of·the·asynchronous·operation.·If·the·socket·is·closed·at·this·time·then | 151 | ····//·of·the·asynchronous·operation.·If·the·socket·is·closed·at·this·time·then |
151 | ····//·the·timeout·handler·must·have·run·first. | 152 | ····//·the·timeout·handler·must·have·run·first. |
152 | ····if·(!socket_.is_open()) | 153 | ····if·(!socket_.is_open()) |
153 | ····{ | 154 | ····{ |
154 | ······std::cout·<<·"Connect·timed·out\n"; | 155 | ······std::cout·<<·"Connect·timed·out\n"; |
155 | | 156 | |
156 | ······//·Try·the·next·available·endpoint. | 157 | ······//·Try·the·next·available·endpoint. |
157 | ······start_connect(++endpoint_iter); | 158 | ······start_connect(++endpoint_iter); |
158 | ····} | 159 | ····} |
159 | | 160 | |
160 | ····//·Check·if·the·connect·operation·failed·before·the·deadline·expired. | 161 | ····//·Check·if·the·connect·operation·failed·before·the·deadline·expired. |
161 | ····else·if·(ec) | 162 | ····else·if·(error) |
162 | ····{ | 163 | ····{ |
163 | ······std::cout·<<·"Connect·error:·"·<<·ec.message()·<<·"\n"; | 164 | ······std::cout·<<·"Connect·error:·"·<<·error.message()·<<·"\n"; |
164 | | 165 | |
165 | ······//·We·need·to·close·the·socket·used·in·the·previous·connection·attempt | 166 | ······//·We·need·to·close·the·socket·used·in·the·previous·connection·attempt |
166 | ······//·before·starting·a·new·one. | 167 | ······//·before·starting·a·new·one. |
167 | ······socket_.close(); | 168 | ······socket_.close(); |
168 | | 169 | |
169 | ······//·Try·the·next·available·endpoint. | 170 | ······//·Try·the·next·available·endpoint. |
170 | ······start_connect(++endpoint_iter); | 171 | ······start_connect(++endpoint_iter); |
171 | ····} | 172 | ····} |
172 | | 173 | |
173 | ····//·Otherwise·we·have·successfully·established·a·connection. | 174 | ····//·Otherwise·we·have·successfully·established·a·connection. |
174 | ····else | 175 | ····else |
175 | ····{ | 176 | ····{ |
176 | ······std::cout·<<·"Connected·to·"·<<·endpoint_iter->endpoint()·<<·"\n"; | 177 | ······std::cout·<<·"Connected·to·"·<<·endpoint_iter->endpoint()·<<·"\n"; |
177 | | 178 | |
178 | ······//·Start·the·input·actor. | 179 | ······//·Start·the·input·actor. |
179 | ······start_read(); | 180 | ······start_read(); |
180 | | 181 | |
181 | ······//·Start·the·heartbeat·actor. | 182 | ······//·Start·the·heartbeat·actor. |
182 | ······start_write(); | 183 | ······start_write(); |
183 | ····} | 184 | ····} |
184 | ··} | 185 | ··} |
185 | | 186 | |
186 | ··void·start_read() | 187 | ··void·start_read() |
187 | ··{ | 188 | ··{ |
188 | ····//·Set·a·deadline·for·the·read·operation. | 189 | ····//·Set·a·deadline·for·the·read·operation. |
189 | ····deadline_.expires_after(asio::chrono::seconds(30)); | 190 | ····deadline_.expires_after(std::chrono::seconds(30)); |
190 | | 191 | |
191 | ····//·Start·an·asynchronous·operation·to·read·a·newline-delimited·message. | 192 | ····//·Start·an·asynchronous·operation·to·read·a·newline-delimited·message. |
192 | ····asio::async_read_until(socket_, | 193 | ····asio::async_read_until(socket_, |
193 | ········asio::dynamic_buffer(input_buffer_),·'\n', | 194 | ········asio::dynamic_buffer(input_buffer_),·'\n', |
194 | ········boost::bind(&client::handle_read,·this, | 195 | ········std::bind(&client::handle_read,·this,·_1,·_2)); |
195 | ··········boost::placeholders::_1,·boost::placeholders::_2)); | |
196 | ··} | 196 | ··} |
197 | | 197 | |
198 | ··void·handle_read(const·asio::error_code&·ec,·std::size_t·n) | 198 | ··void·handle_read(const·std::error_code&·error,·std::size_t·n) |
199 | ··{ | 199 | ··{ |
200 | ····if·(stopped_) | 200 | ····if·(stopped_) |
201 | ······return; | 201 | ······return; |
202 | | 202 | |
203 | ····if·(!ec) | 203 | ····if·(!error) |
204 | ····{ | 204 | ····{ |
205 | ······//·Extract·the·newline-delimited·message·from·the·buffer. | 205 | ······//·Extract·the·newline-delimited·message·from·the·buffer. |
206 | ······std::string·line(input_buffer_.substr(0,·n·-·1)); | 206 | ······std::string·line(input_buffer_.substr(0,·n·-·1)); |
207 | ······input_buffer_.erase(0,·n); | 207 | ······input_buffer_.erase(0,·n); |
208 | | 208 | |
209 | ······//·Empty·messages·are·heartbeats·and·so·ignored. | 209 | ······//·Empty·messages·are·heartbeats·and·so·ignored. |
210 | ······if·(!line.empty()) | 210 | ······if·(!line.empty()) |
211 | ······{ | 211 | ······{ |
212 | ········std::cout·<<·"Received:·"·<<·line·<<·"\n"; | 212 | ········std::cout·<<·"Received:·"·<<·line·<<·"\n"; |
213 | ······} | 213 | ······} |
214 | | 214 | |
215 | ······start_read(); | 215 | ······start_read(); |
216 | ····} | 216 | ····} |
217 | ····else | 217 | ····else |
218 | ····{ | 218 | ····{ |
219 | ······std::cout·<<·"Error·on·receive:·"·<<·ec.message()·<<·"\n"; | 219 | ······std::cout·<<·"Error·on·receive:·"·<<·error.message()·<<·"\n"; |
220 | | 220 | |
221 | ······stop(); | 221 | ······stop(); |
222 | ····} | 222 | ····} |
223 | ··} | 223 | ··} |
224 | | 224 | |
225 | ··void·start_write() | 225 | ··void·start_write() |
226 | ··{ | 226 | ··{ |
227 | ····if·(stopped_) | 227 | ····if·(stopped_) |
228 | ······return; | 228 | ······return; |
229 | | 229 | |
230 | ····//·Start·an·asynchronous·operation·to·send·a·heartbeat·message. | 230 | ····//·Start·an·asynchronous·operation·to·send·a·heartbeat·message. |
231 | ····asio::async_write(socket_,·asio::buffer("\n",·1), | 231 | ····asio::async_write(socket_,·asio::buffer("\n",·1), |
232 | ········boost::bind(&client::handle_write,·this,·boost::placeholders::_1)); | 232 | ········std::bind(&client::handle_write,·this,·_1)); |
233 | ··} | 233 | ··} |
234 | | 234 | |
235 | ··void·handle_write(const·asio::error_code&·ec) | 235 | ··void·handle_write(const·std::error_code&·error) |
236 | ··{ | 236 | ··{ |
237 | ····if·(stopped_) | 237 | ····if·(stopped_) |
238 | ······return; | 238 | ······return; |
239 | | 239 | |
240 | ····if·(!ec) | 240 | ····if·(!error) |
241 | ····{ | 241 | ····{ |
242 | ······//·Wait·10·seconds·before·sending·the·next·heartbeat. | 242 | ······//·Wait·10·seconds·before·sending·the·next·heartbeat. |
243 | ······heartbeat_timer_.expires_after(asio::chrono::seconds(10)); | 243 | ······heartbeat_timer_.expires_after(std::chrono::seconds(10)); |
244 | ······heartbeat_timer_.async_wait(boost::bind(&client::start_write,·this)); | 244 | ······heartbeat_timer_.async_wait(std::bind(&client::start_write,·this)); |
245 | ····} | 245 | ····} |
246 | ····else | 246 | ····else |
247 | ····{ | 247 | ····{ |
248 | ······std::cout·<<·"Error·on·heartbeat:·"·<<·ec.message()·<<·"\n"; | 248 | ······std::cout·<<·"Error·on·heartbeat:·"·<<·error.message()·<<·"\n"; |
249 | | 249 | |
250 | ······stop(); | 250 | ······stop(); |
251 | ····} | 251 | ····} |
252 | ··} | 252 | ··} |
253 | | 253 | |
254 | ··void·check_deadline() | 254 | ··void·check_deadline() |
255 | ··{ | 255 | ··{ |
256 | ····if·(stopped_) | 256 | ····if·(stopped_) |
257 | ······return; | 257 | ······return; |
258 | | 258 | |
259 | ····//·Check·whether·the·deadline·has·passed.·We·compare·the·deadline·against | 259 | ····//·Check·whether·the·deadline·has·passed.·We·compare·the·deadline·against |
260 | ····//·the·current·time·since·a·new·asynchronous·operation·may·have·moved·the | 260 | ····//·the·current·time·since·a·new·asynchronous·operation·may·have·moved·the |
261 | ····//·deadline·before·this·actor·had·a·chance·to·run. | 261 | ····//·deadline·before·this·actor·had·a·chance·to·run. |
262 | ····if·(deadline_.expiry()·<=·steady_timer::clock_type::now()) | 262 | ····if·(deadline_.expiry()·<=·steady_timer::clock_type::now()) |
263 | ····{ | 263 | ····{ |
264 | ······//·The·deadline·has·passed.·The·socket·is·closed·so·that·any·outstanding | 264 | ······//·The·deadline·has·passed.·The·socket·is·closed·so·that·any·outstanding |
265 | ······//·asynchronous·operations·are·cancelled. | 265 | ······//·asynchronous·operations·are·cancelled. |
266 | ······socket_.close(); | 266 | ······socket_.close(); |
267 | | 267 | |
268 | ······//·There·is·no·longer·an·active·deadline.·The·expiry·is·set·to·the | 268 | ······//·There·is·no·longer·an·active·deadline.·The·expiry·is·set·to·the |
269 | ······//·maximum·time·point·so·that·the·actor·takes·no·action·until·a·new | 269 | ······//·maximum·time·point·so·that·the·actor·takes·no·action·until·a·new |
270 | ······//·deadline·is·set. | 270 | ······//·deadline·is·set. |
271 | ······deadline_.expires_at(steady_timer::time_point::max()); | 271 | ······deadline_.expires_at(steady_timer::time_point::max()); |
272 | ····} | 272 | ····} |
273 | | 273 | |
274 | ····//·Put·the·actor·back·to·sleep. | 274 | ····//·Put·the·actor·back·to·sleep. |
275 | ····deadline_.async_wait(boost::bind(&client::check_deadline,·this)); | 275 | ····deadline_.async_wait(std::bind(&client::check_deadline,·this)); |
276 | ··} | 276 | ··} |
277 | | 277 | |
278 | private: | 278 | private: |
279 | ··bool·stopped_; | 279 | ··bool·stopped_·=·false; |
280 | ··tcp::resolver::results_type·endpoints_; | 280 | ··tcp::resolver::results_type·endpoints_; |
281 | ··tcp::socket·socket_; | 281 | ··tcp::socket·socket_; |
282 | ··std::string·input_buffer_; | 282 | ··std::string·input_buffer_; |
283 | ··steady_timer·deadline_; | 283 | ··steady_timer·deadline_; |
284 | ··steady_timer·heartbeat_timer_; | 284 | ··steady_timer·heartbeat_timer_; |
285 | }; | 285 | }; |
286 | | 286 | |
287 | int·main(int·argc,·char*·argv[]) | 287 | int·main(int·argc,·char*·argv[]) |
288 | { | 288 | { |
289 | ··try | 289 | ··try |
290 | ··{ | 290 | ··{ |
291 | ····if·(argc·!=·3) | 291 | ····if·(argc·!=·3) |
292 | ····{ | 292 | ····{ |
293 | ······std::cerr·<<·"Usage:·client·<host>·<port>\n"; | 293 | ······std::cerr·<<·"Usage:·client·<host>·<port>\n"; |
294 | ······return·1; | 294 | ······return·1; |
295 | ····} | 295 | ····} |
296 | | 296 | |
297 | ····asio::io_context·io_context; | 297 | ····asio::io_context·io_context; |
298 | ····tcp::resolver·r(io_context); | 298 | ····tcp::resolver·r(io_context); |
299 | ····client·c(io_context); | 299 | ····client·c(io_context); |
300 | | 300 | |
301 | ····c.start(r.resolve(argv[1],·argv[2])); | 301 | ····c.start(r.resolve(argv[1],·argv[2])); |
302 | | 302 | |
303 | ····io_context.run(); | 303 | ····io_context.run(); |
304 | ··} | 304 | ··} |
305 | ··catch·(std::exception&·e) | 305 | ··catch·(std::exception&·e) |
306 | ··{ | 306 | ··{ |
307 | ····std::cerr·<<·"Exception:·"·<<·e.what()·<<·"\n"; | 307 | ····std::cerr·<<·"Exception:·"·<<·e.what()·<<·"\n"; |
308 | ··} | 308 | ··} |
309 | | 309 | |
310 | ··return·0; | 310 | ··return·0; |
311 | } | 311 | } |