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·​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·​=·​socket_.​async_read_some(asio:​:​buffer(data)​,​·​yield)​;​
45 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​asio:​:​async_write(socket_,​·​asio:​:​buffer(data,​·​n)​,​·​yield)​;​
46 ·​·​·​·​·​·​·​·​·​·​·​·​}
47 ·​·​·​·​·​·​·​·​·​·​}
48 ·​·​·​·​·​·​·​·​·​·​catch·​(std:​:​exception&·​e)​
49 ·​·​·​·​·​·​·​·​·​·​{
50 ·​·​·​·​·​·​·​·​·​·​·​·​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 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​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·​=·​socket_.​async_read_some(asio:​:​buffer(data)​,​·​yield)​;​
61 ·​·​·​·​·​·​·​·​asio:​:​async_write(socket_,​·​asio:​:​buffer(data,​·​n)​,​·​yield)​;​
62 ·​·​·​·​·​·​}
63 ·​·​·​·​}
64 ·​·​·​·​catch·​(std:​:​exception&·​e)​
65 ·​·​·​·​{
66 ·​·​·​·​·​·​socket_.​close()​;​
67 ·​·​·​·​·​·​timer_.​cancel()​;​
68 ·​·​·​·​}
69 ·​·​}
70
71 ·​·​void·​timeout(asio:​:​yield_context·​yield)​
72 ·​·​{
73 ·​·​·​·​while·​(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 ·​·​·​·​·​·​·​·​socket_.​close()​;​
79 ·​·​·​·​}
80 ·​·​}
81
82 ·​·​asio:​:​strand<asio:​:​io_context:​:​executor_type>·​strand_;​
83 ·​·​tcp:​:​socket·​socket_;​69 ·​·​tcp:​:​socket·​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 }