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