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-​2020·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2020·​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 }