src/​examples/​cpp03/​spawn/​echo_server.​cppsrc/​examples/​cpp11/​spawn/​echo_server.​cpp
1 /​/​1 /​/​
2 /​/​·​echo_server.​cpp2 /​/​·​echo_server.​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·​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/​io_context.​hpp>11 #include·​<asio/​io_context.​hpp>
12 #include·​<asio/​ip/​tcp.​hpp>12 #include·​<asio/​ip/​tcp.​hpp>
13 #include·​<asio/​spawn.​hpp>13 #include·​<asio/​spawn.​hpp>
14 #include·​<asio/​steady_timer.​hpp>14 #include·​<asio/​steady_timer.​hpp>
15 #include·​<asio/​write.​hpp>15 #include·​<asio/​write.​hpp>
16 #include·​<boost/​bind/​bind.​hpp>
17 #include·​<boost/​shared_ptr.​hpp>
18 #include·​<boost/​enable_shared_from_th​is.​hpp>
19 #include·​<iostream>16 #include·​<iostream>
17 #include·​<memory>
20 18
21 using·​asio:​:​ip:​:​tcp;​19 using·​asio:​:​ip:​:​tcp;​
22 20
23 class·​session·​:​·​public·boost:​:​enable_shared_from_th​is<session>21 class·​session·​:​·​public·​std:​:​enable_shared_from_th​is<session>
24 {22 {
25 public:​23 public:​
26 ··​explicit·​session(asio:​:​io_context&·​io_context)​24 ··​explicit·​session(asio:​:​io_context&·​io_context,​·tcp:​:​socket·socket)​
27 ····​:​·​strand_(asio:​:​make_strand(io_contex​t)​)​,​25 ····​:​·​socket_(std:​:​move(socket)​)​,​
28 ······socket_(io_context)​,​26 ······timer_(io_context)​,​
29 ······​timer_(io_context)​27 ······strand_(io_context.​get_executor()​)​
30 ··​{28 ··​{
31 ··​}29 ··​}
32 30
33 ··​tcp:​:​socket&·​socket()​
34 ··​{
35 ····​return·​socket_;​
36 ··​}
37
38 ··​void·​go()​31 ··​void·​go()​
39 ··​{32 ··​{
33 ····​auto·​self(shared_from_this​()​)​;​
40 ····​asio:​:​spawn(strand_,​34 ····​asio:​:​spawn(strand_,​
41 ········boost:​:​bind(&session:​:​echo,​35 ········[this,​·self](asio:​:​yield_context·yield)​
42 ··········shared_from_this()​,​·boost:​:​placeholders:​:​_1)​)​;​36 ········{
37 ··········​try
38 ··········​{
39 ············​char·​data[128];​
40 ············​for·​(;​;​)​
41 ············​{
42 ··············​timer_.​expires_from_now(std:​:​chrono:​:​seconds(10)​)​;​
43 ··············​std:​:​size_t·​n·​=·​socket_.​async_read_some(asio:​:​buffer(data)​,​·​yield)​;​
44 ··············​asio:​:​async_write(socket_,​·​asio:​:​buffer(data,​·​n)​,​·​yield)​;​
45 ············​}
46 ··········​}
47 ··········​catch·​(std:​:​exception&·​e)​
48 ··········​{
49 ············​socket_.​close()​;​
50 ············​timer_.​cancel()​;​
51 ··········​}
52 ········​})​;​
53
43 ····​asio:​:​spawn(strand_,​54 ····​asio:​:​spawn(strand_,​
44 ········boost:​:​bind(&session:​:​timeout,​55 ········[this,​·self](asio:​:​yield_context·yield)​
45 ··········shared_from_this()​,​·boost:​:​placeholders:​:​_1)​)​;​56 ········{
57 ··········​while·​(socket_.​is_open()​)​
58 ··········​{
59 ············​asio:​:​error_code·​ignored_ec;​
60 ············​timer_.​async_wait(yield[igno​red_ec])​;​
61 ············​if·​(timer_.​expires_from_now()​·​<=·​std:​:​chrono:​:​seconds(0)​)​
62 ··············​socket_.​close()​;​
63 ··········​}
64 ········​})​;​
46 ··​}65 ··​}
47 66
48 private:​67 private:​
49 ··​void·​echo(asio:​:​yield_context·​yield)​
50 ··​{
51 ····​try
52 ····​{
53 ······​char·​data[128];​
54 ······​for·​(;​;​)​
55 ······​{
56 ········​timer_.​expires_after(asio:​:​chrono:​:​seconds(10)​)​;​
57 ········​std:​:​size_t·​n·​=·​socket_.​async_read_some(asio:​:​buffer(data)​,​·​yield)​;​
58 ········​asio:​:​async_write(socket_,​·​asio:​:​buffer(data,​·​n)​,​·​yield)​;​
59 ······​}
60 ····​}
61 ····​catch·​(std:​:​exception&·​e)​
62 ····​{
63 ······​socket_.​close()​;​
64 ······​timer_.​cancel()​;​
65 ····​}
66 ··​}
67
68 ··​void·​timeout(asio:​:​yield_context·​yield)​
69 ··​{
70 ····​while·​(socket_.​is_open()​)​
71 ····​{
72 ······​asio:​:​error_code·​ignored_ec;​
73 ······​timer_.​async_wait(yield[igno​red_ec])​;​
74 ······​if·​(timer_.​expiry()​·​<=·​asio:​:​steady_timer:​:​clock_type:​:​now()​)​
75 ········​socket_.​close()​;​
76 ····​}
77 ··​}
78
79 ··​asio:​:​strand<asio:​:​io_context:​:​executor_type>·​strand_;​
80 ··​tcp:​:​socket·​socket_;​68 ··​tcp:​:​socket·​socket_;​
81 ··​asio:​:​steady_timer·​timer_;​69 ··​asio:​:​steady_timer·​timer_;​
70 ··​asio:​:​strand<asio:​:​io_context:​:​executor_type>·​strand_;​
82 };​71 };​
83 72
84 void·​do_accept(asio:​:​io_context&·​io_context,​
85 ····​unsigned·​short·​port,​·​asio:​:​yield_context·​yield)​
86 {
87 ··​tcp:​:​acceptor·​acceptor(io_context,​·​tcp:​:​endpoint(tcp:​:​v4()​,​·​port)​)​;​
88
89 ··​for·​(;​;​)​
90 ··​{
91 ····​asio:​:​error_code·​ec;​
92 ····​boost:​:​shared_ptr<session>·​new_session(new·​session(io_context)​)​;​
93 ····​acceptor.​async_accept(new_sess​ion-​>socket()​,​·​yield[ec])​;​
94 ····​if·​(!ec)​·​new_session-​>go()​;​
95 ··​}
96 }
97
98 int·​main(int·​argc,​·​char*·​argv[])​73 int·​main(int·​argc,​·​char*·​argv[])​
99 {74 {
100 ··​try75 ··​try
101 ··​{76 ··​{
102 ····​if·​(argc·​!=·​2)​77 ····​if·​(argc·​!=·​2)​
103 ····​{78 ····​{
104 ······​std:​:​cerr·​<<·​"Usage:​·​echo_server·​<port>\n";​79 ······​std:​:​cerr·​<<·​"Usage:​·​echo_server·​<port>\n";​
105 ······​return·​1;​80 ······​return·​1;​
106 ····​}81 ····​}
107 82
108 ····​asio:​:​io_context·​io_context;​83 ····​asio:​:​io_context·​io_context;​
109 84
110 ····​asio:​:​spawn(io_context,​85 ····​asio:​:​spawn(io_context,​
111 ········boost:​:​bind(do_accept,​86 ········[&](asio:​:​yield_context·yield)​
112 ··········boost:​:​ref(io_context)​,​·atoi(argv[1])​,​·boost:​:​placeholders:​:​_1)​)​;​87 ········{
88 ··········​tcp:​:​acceptor·​acceptor(io_context,​
89 ············​tcp:​:​endpoint(tcp:​:​v4()​,​·​std:​:​atoi(argv[1])​)​)​;​
90
91 ··········​for·​(;​;​)​
92 ··········​{
93 ············​asio:​:​error_code·​ec;​
94 ············​tcp:​:​socket·​socket(io_context)​;​
95 ············​acceptor.​async_accept(socket,​·​yield[ec])​;​
96 ············​if·​(!ec)​
97 ············​{
98 ··············​std:​:​make_shared<session>(​io_context,​·​std:​:​move(socket)​)​-​>go()​;​
99 ············​}
100 ··········​}
101 ········​})​;​
113 102
114 ····​io_context.​run()​;​103 ····​io_context.​run()​;​
115 ··​}104 ··​}
116 ··​catch·​(std:​:​exception&·​e)​105 ··​catch·​(std:​:​exception&·​e)​
117 ··​{106 ··​{
118 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​107 ····​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​
119 ··​}108 ··​}
120 109
121 ··​return·​0;​110 ··​return·​0;​
122 }111 }