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