| 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-2021·Christopher·M.·Kohlhoff·(chris·at·kohlhoff·dot·com) | 5 | //·Copyright·(c)·2003-2021·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 | } |