src/​examples/​cpp03/​http/​server/​server.​cpp | src/​examples/​cpp11/​http/​server/​server.​cpp
--- | ---
⋮ | ⋮
1 | /​/​ | 1 | /​/​
2 | /​/​·​server.​cpp | 2 | /​/​·​server.​cpp
3 | /​/​·​~~~~~~~~~~ | 3 | /​/​·​~~~~~~~~~~
4 | /​/​ | 4 | /​/​
5 | /​/​·​Copyright·​(c)​·​2003-​2022·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​ | 5 | /​/​·​Copyright·​(c)​·​2003-​2022·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​
6 | /​/​ | 6 | /​/​
7 | /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying | 7 | /​/​·​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·​"server.​hpp" | 11 | #include·​"server.​hpp"
12 | #include·​<boost/​bind/​bind.​hpp> |
13 | #include·​<signal.​h> | 12 | #include·​<signal.​h>
| 13 | #include·​<utility>
14 |  | 14 |
15 | namespace·​http·​{ | 15 | namespace·​http·​{
16 | namespace·​server·​{ | 16 | namespace·​server·​{
17 |  | 17 |
18 | server:​:​server(const·​std:​:​string&·​address,​·​const·​std:​:​string&·​port,​ | 18 | server:​:​server(const·​std:​:​string&·​address,​·​const·​std:​:​string&·​port,​
19 | ·​·​·​·​const·​std:​:​string&·​doc_root)​ | 19 | ·​·​·​·​const·​std:​:​string&·​doc_root)​
20 | ·​·​:​·​io_context_()​,​ | 20 | ·​·​:​·​io_context_(1)​,​
21 | ·​·​·​·​signals_(io_context_)​,​ | 21 | ·​·​·​·​signals_(io_context_)​,​
22 | ·​·​·​·​acceptor_(io_context_​)​,​ | 22 | ·​·​·​·​acceptor_(io_context_​)​,​
23 | ·​·​·​·​connection_manager_()​,​ | 23 | ·​·​·​·​connection_manager_()​,​
24 | ·​·​·​·​new_connection_()​,​ |
25 | ·​·​·​·​request_handler_(doc_​root)​ | 24 | ·​·​·​·​request_handler_(doc_​root)​
26 | { | 25 | {
27 | ·​·​/​/​·​Register·​to·​handle·​the·​signals·​that·​indicate·​when·​the·​server·​should·​exit.​ | 26 | ·​·​/​/​·​Register·​to·​handle·​the·​signals·​that·​indicate·​when·​the·​server·​should·​exit.​
28 | ·​·​/​/​·​It·​is·​safe·​to·​register·​for·​the·​same·​signal·​multiple·​times·​in·​a·​program,​ | 27 | ·​·​/​/​·​It·​is·​safe·​to·​register·​for·​the·​same·​signal·​multiple·​times·​in·​a·​program,​
29 | ·​·​/​/​·​provided·​all·​registration·​for·​the·​specified·​signal·​is·​made·​through·​Asio.​ | 28 | ·​·​/​/​·​provided·​all·​registration·​for·​the·​specified·​signal·​is·​made·​through·​Asio.​
30 | ·​·​signals_.​add(SIGINT)​;​ | 29 | ·​·​signals_.​add(SIGINT)​;​
31 | ·​·​signals_.​add(SIGTERM)​;​ | 30 | ·​·​signals_.​add(SIGTERM)​;​
32 | #if·​defined(SIGQUIT)​ | 31 | #if·​defined(SIGQUIT)​
33 | ·​·​signals_.​add(SIGQUIT)​;​ | 32 | ·​·​signals_.​add(SIGQUIT)​;​
34 | #endif·​/​/​·​defined(SIGQUIT)​ | 33 | #endif·​/​/​·​defined(SIGQUIT)​
35 | ·​·​signals_.​async_wait(boost:​:​bind(&server:​:​handle_stop,​·​this)​)​;​ |
36 |  | 34 |
| 35 | ·​·​do_await_stop()​;​
| 36 |
37 | ·​·​/​/​·​Open·​the·​acceptor·​with·​the·​option·​to·​reuse·​the·​address·​(i.​e.​·​SO_REUSEADDR)​.​ | 37 | ·​·​/​/​·​Open·​the·​acceptor·​with·​the·​option·​to·​reuse·​the·​address·​(i.​e.​·​SO_REUSEADDR)​.​
38 | ·​·​asio:​:​ip:​:​tcp:​:​resolver·​resolver(io_context_)​;​ | 38 | ·​·​asio:​:​ip:​:​tcp:​:​resolver·​resolver(io_context_)​;​
39 | ·​·​asio:​:​ip:​:​tcp:​:​endpoint·​endpoint·​= | 39 | ·​·​asio:​:​ip:​:​tcp:​:​endpoint·​endpoint·​=
40 | ·​·​·​·​*resolver.​resolve(address,​·​port)​.​begin()​;​ | 40 | ·​·​·​·​*resolver.​resolve(address,​·​port)​.​begin()​;​
41 | ·​·​acceptor_.​open(endpoint.​protocol()​)​;​ | 41 | ·​·​acceptor_.​open(endpoint.​protocol()​)​;​
42 | ·​·​acceptor_.​set_option(asio:​:​ip:​:​tcp:​:​acceptor:​:​reuse_address(true)​)​;​ | 42 | ·​·​acceptor_.​set_option(asio:​:​ip:​:​tcp:​:​acceptor:​:​reuse_address(true)​)​;​
43 | ·​·​acceptor_.​bind(endpoint)​;​ | 43 | ·​·​acceptor_.​bind(endpoint)​;​
44 | ·​·​acceptor_.​listen()​;​ | 44 | ·​·​acceptor_.​listen()​;​
45 |  | 45 |
46 | ·​·​start_accept()​;​ | 46 | ·​·​do_accept()​;​
47 | } | 47 | }
48 |  | 48 |
49 | void·​server:​:​run()​ | 49 | void·​server:​:​run()​
50 | { | 50 | {
51 | ·​·​/​/​·​The·​io_context:​:​run()​·​call·​will·​block·​until·​all·​asynchronous·​operations | 51 | ·​·​/​/​·​The·​io_context:​:​run()​·​call·​will·​block·​until·​all·​asynchronous·​operations
52 | ·​·​/​/​·​have·​finished.​·​While·​the·​server·​is·​running,​·​there·​is·​always·​at·​least·​one | 52 | ·​·​/​/​·​have·​finished.​·​While·​the·​server·​is·​running,​·​there·​is·​always·​at·​least·​one
53 | ·​·​/​/​·​asynchronous·​operation·​outstanding:​·​the·​asynchronous·​accept·​call·​waiting | 53 | ·​·​/​/​·​asynchronous·​operation·​outstanding:​·​the·​asynchronous·​accept·​call·​waiting
54 | ·​·​/​/​·​for·​new·​incoming·​connections.​ | 54 | ·​·​/​/​·​for·​new·​incoming·​connections.​
55 | ·​·​io_context_.​run()​;​ | 55 | ·​·​io_context_.​run()​;​
56 | } | 56 | }
57 |  | 57 |
58 | void·​server:​:​start_accept()​ | 58 | void·​server:​:​do_accept()​
59 | { | 59 | {
60 | ·​·​new_connection_.​reset(new·​connection(io_context​_,​ | 60 | ·​·​acceptor_.​async_accept(
61 | ·​·​·​·​·​·​·​·​connection_manager_,​·​request_handler_)​)​;​ | 61 | ·​·​·​·​·​·​[this](std:​:​error_code·​ec,​·​asio:​:​ip:​:​tcp:​:​socket·​socket)​
62 | ·​·​acceptor_.​async_accept(new_conn​ection_-​>socket()​,​ | 62 | ·​·​·​·​·​·​{
63 | ·​·​·​·​·​·​boost:​:​bind(&server:​:​handle_accept,​·​this,​ | 63 | ·​·​·​·​·​·​·​·​/​/​·​Check·​whether·​the·​server·​was·​stopped·​by·​a·​signal·​before·​this
64 | ·​·​·​·​·​·​·​·​asio:​:​placeholders:​:​error)​)​;​ | 64 | ·​·​·​·​·​·​·​·​/​/​·​completion·​handler·​had·​a·​chance·​to·​run.​
65 | } | 65 | ·​·​·​·​·​·​·​·​if·​(!acceptor_.​is_open()​)​
| 66 | ·​·​·​·​·​·​·​·​{
| 67 | ·​·​·​·​·​·​·​·​·​·​return;​
| 68 | ·​·​·​·​·​·​·​·​}
66 |  | 69 |
67 | void·​server:​:​handle_accept(const·​asio:​:​error_code&·​e)​ | 70 | ·​·​·​·​·​·​·​·​if·​(!ec)​
68 | { | 71 | ·​·​·​·​·​·​·​·​{
69 | ·​·​/​/​·​Check·​whether·​the·​server·​was·​stopped·​by·​a·​signal·​before·​this·​completion | 72 | ·​·​·​·​·​·​·​·​·​·​connection_manager_.​start(std:​:​make_shared<connectio​n>(
70 | ·​·​/​/​·​handler·​had·​a·​chance·​to·​run.​ | 73 | ·​·​·​·​·​·​·​·​·​·​·​·​·​·​std:​:​move(socket)​,​·​connection_manager_,​·​request_handler_)​)​;​
71 | ·​·​if·​(!acceptor_.​is_open()​)​ | 74 | ·​·​·​·​·​·​·​·​}
72 | ·​·​{ |
73 | ·​·​·​·​return;​ |
74 | ·​·​} |
75 |  | 75 |
76 | ·​·​if·​(!e)​ | 76 | ·​·​·​·​·​·​·​·​do_accept()​;​
77 | ·​·​{ | 77 | ·​·​·​·​·​·​})​;​
78 | ·​·​·​·​connection_manager_.​start(new_connection_​)​;​ |
79 | ·​·​} |
80 |  |
81 | ·​·​start_accept()​;​ |
82 | } | 78 | }
83 |  | 79 |
84 | void·​server:​:​handle_stop()​ | 80 | void·​server:​:​do_await_stop()​
85 | { | 81 | {
86 | ·​·​/​/​·​The·​server·​is·​stopped·​by·​cancelling·​all·​outstanding·​asynchronous | 82 | ·​·​signals_.​async_wait(
87 | ·​·​/​/​·​operations.​·​Once·​all·​operations·​have·​finished·​the·​io_context:​:​run()​·​call | 83 | ·​·​·​·​·​·​[this](std:​:​error_code·​/​*ec*/​,​·​int·​/​*signo*/​)​
88 | ·​·​/​/​·​will·​exit.​ | 84 | ·​·​·​·​·​·​{
89 | ·​·​acceptor_.​close()​;​ | 85 | ·​·​·​·​·​·​·​·​/​/​·​The·​server·​is·​stopped·​by·​cancelling·​all·​outstanding·​asynchronous
90 | ·​·​connection_manager_.​stop_all()​;​ | 86 | ·​·​·​·​·​·​·​·​/​/​·​operations.​·​Once·​all·​operations·​have·​finished·​the·​io_context:​:​run()​
| 87 | ·​·​·​·​·​·​·​·​/​/​·​call·​will·​exit.​
| 88 | ·​·​·​·​·​·​·​·​acceptor_.​close()​;​
| 89 | ·​·​·​·​·​·​·​·​connection_manager_.​stop_all()​;​
| 90 | ·​·​·​·​·​·​})​;​
91 | } | 91 | }
92 |  | 92 |
93 | }·​/​/​·​namespace·​server | 93 | }·​/​/​·​namespace·​server
94 | }·​/​/​·​namespace·​http | 94 | }·​/​/​·​namespace·​http