| 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 | } |