src/​examples/​cpp03/​timeouts/​async_tcp_client.​cppsrc/​examples/​cpp11/​timeouts/​async_tcp_client.​cpp
⋮⋮
1 /​/​1 /​/​
2 /​/​·​async_tcp_client.​cpp2 /​/​·​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·​accompanying7 /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying
8 /​/​·​file·​LICENSE_1_0.​txt·​or·​copy·​at·​http:​/​/​www.​boost.​org/​LICENSE_1_0.​txt)​8 /​/​·​file·​LICENSE_1_0.​txt·​or·​copy·​at·​http:​/​/​www.​boost.​org/​LICENSE_1_0.​txt)​
9 /​/​9 /​/​
10 10
11 #include·​"asio/​buffer.​hpp"11 #include·​"asio/​buffer.​hpp"
12 #include·​"asio/​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·​the29 /​/​·​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·​socket40 /​/​·​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·​a43 /​/​·​Connection·​establishment·​involves·​trying·​each·​endpoint·​in·​turn·​until·​a
42 /​/​·​connection·​is·​successful,​·​or·​the·​available·​endpoints·​are·​exhausted.​·​If·​the44 /​/​·​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·​to45 /​/​·​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·​for64 /​/​·​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·​delimited79 /​/​·​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·​single82 /​/​·​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·​applied83 /​/​·​newline·​character)​·​every·​10·​seconds.​·​In·​this·​example,​·​no·​deadline·​is·​applied
82 /​/​·​to·​message·​sending.​84 /​/​·​to·​message·​sending.​
83 /​/​85 /​/​
84 class·​client86 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_c​ontext)​92 ·​·​·​·​·​·​heartbeat_timer_(io_c​ontext)​
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(endpoin​ts_.​begin()​)​;​102 ·​·​·​·​start_connect(endpoin​ts_.​begin()​)​;​
102 103
103 ·​·​·​·​/​/​·​Start·​the·​deadline·​actor.​·​You·​will·​note·​that·​we're·​not·​setting·​any104 ·​·​·​·​/​/​·​Start·​the·​deadline·​actor.​·​You·​will·​note·​that·​we're·​not·​setting·​any
104 ·​·​·​·​/​/​·​particular·​deadline·​here.​·​Instead,​·​the·​connect·​and·​input·​actors·​will105 ·​·​·​·​/​/​·​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.​·​It110 ·​·​/​/​·​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·​in111 ·​·​/​/​·​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(endpoin​t_iter-​>endpoint()​,​133 ·​·​·​·​·​·​socket_.​async_connect(endpoin​t_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 ·​·​·​·​else137 ·​·​·​·​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·​start150 ·​·​·​·​/​/​·​The·​async_connect()​·​function·​automatically·​opens·​the·​socket·​at·​the·​start
150 ·​·​·​·​/​/​·​of·​the·​asynchronous·​operation.​·​If·​the·​socket·​is·​closed·​at·​this·​time·​then151 ·​·​·​·​/​/​·​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(++endpo​int_iter)​;​158 ·​·​·​·​·​·​start_connect(++endpo​int_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·​attempt166 ·​·​·​·​·​·​/​/​·​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(++endpo​int_iter)​;​171 ·​·​·​·​·​·​start_connect(++endpo​int_iter)​;​
171 ·​·​·​·​}172 ·​·​·​·​}
172 173
173 ·​·​·​·​/​/​·​Otherwise·​we·​have·​successfully·​established·​a·​connection.​174 ·​·​·​·​/​/​·​Otherwise·​we·​have·​successfully·​established·​a·​connection.​
174 ·​·​·​·​else175 ·​·​·​·​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(sock​et_,​193 ·​·​·​·​asio:​:​async_read_until(sock​et_,​
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 ·​·​·​·​else217 ·​·​·​·​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 ·​·​·​·​else246 ·​·​·​·​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·​against259 ·​·​·​·​/​/​·​Check·​whether·​the·​deadline·​has·​passed.​·​We·​compare·​the·​deadline·​against
260 ·​·​·​·​/​/​·​the·​current·​time·​since·​a·​new·​asynchronous·​operation·​may·​have·​moved·​the260 ·​·​·​·​/​/​·​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·​outstanding264 ·​·​·​·​·​·​/​/​·​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·​the268 ·​·​·​·​·​·​/​/​·​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·​new269 ·​·​·​·​·​·​/​/​·​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_tim​er:​:​time_point:​:​max()​)​;​271 ·​·​·​·​·​·​deadline_.​expires_at(steady_tim​er:​:​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 ·​·​try289 ·​·​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 }