src/​examples/​cpp03/​http/​server/​server.​cppsrc/​examples/​cpp11/​http/​server/​server.​cpp
⋮⋮
1 /​/​1 /​/​
2 /​/​·​server.​cpp2 /​/​·​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·​"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·​operations51 ·​·​/​/​·​The·​io_context:​:​run()​·​call·​will·​block·​until·​all·​asynchronous·​operations
52 ·​·​/​/​·​have·​finished.​·​While·​the·​server·​is·​running,​·​there·​is·​always·​at·​least·​one52 ·​·​/​/​·​have·​finished.​·​While·​the·​server·​is·​running,​·​there·​is·​always·​at·​least·​one
53 ·​·​/​/​·​asynchronous·​operation·​outstanding:​·​the·​asynchronous·​accept·​call·​waiting53 ·​·​/​/​·​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·​completion72 ·​·​·​·​·​·​·​·​·​·​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·​asynchronous82 ·​·​signals_.​async_wait(
87 ·​·​/​/​·​operations.​·​Once·​all·​operations·​have·​finished·​the·​io_context:​:​run()​·​call83 ·​·​·​·​·​·​[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·​server93 }·​/​/​·​namespace·​server
94 }·​/​/​·​namespace·​http94 }·​/​/​·​namespace·​http