• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/vinniefalco/CppCon2018
8 //
9 
10 //------------------------------------------------------------------------------
11 /*
12     WebSocket chat server, multi-threaded
13 
14     This implements a multi-user chat room using WebSocket. The
15     `io_context` runs on any number of threads, specified at
16     the command line.
17 
18 */
19 //------------------------------------------------------------------------------
20 
21 #include "listener.hpp"
22 #include "shared_state.hpp"
23 
24 #include <boost/asio/signal_set.hpp>
25 #include <boost/smart_ptr.hpp>
26 #include <iostream>
27 #include <vector>
28 
29 int
main(int argc,char * argv[])30 main(int argc, char* argv[])
31 {
32     // Check command line arguments.
33     if (argc != 5)
34     {
35         std::cerr <<
36             "Usage: websocket-chat-multi <address> <port> <doc_root> <threads>\n" <<
37             "Example:\n" <<
38             "    websocket-chat-server 0.0.0.0 8080 . 5\n";
39         return EXIT_FAILURE;
40     }
41     auto address = net::ip::make_address(argv[1]);
42     auto port = static_cast<unsigned short>(std::atoi(argv[2]));
43     auto doc_root = argv[3];
44     auto const threads = std::max<int>(1, std::atoi(argv[4]));
45 
46     // The io_context is required for all I/O
47     net::io_context ioc;
48 
49     // Create and launch a listening port
50     boost::make_shared<listener>(
51         ioc,
52         tcp::endpoint{address, port},
53         boost::make_shared<shared_state>(doc_root))->run();
54 
55     // Capture SIGINT and SIGTERM to perform a clean shutdown
56     net::signal_set signals(ioc, SIGINT, SIGTERM);
57     signals.async_wait(
58         [&ioc](boost::system::error_code const&, int)
59         {
60             // Stop the io_context. This will cause run()
61             // to return immediately, eventually destroying the
62             // io_context and any remaining handlers in it.
63             ioc.stop();
64         });
65 
66     // Run the I/O service on the requested number of threads
67     std::vector<std::thread> v;
68     v.reserve(threads - 1);
69     for(auto i = threads - 1; i > 0; --i)
70         v.emplace_back(
71         [&ioc]
72         {
73             ioc.run();
74         });
75     ioc.run();
76 
77     // (If we get here, it means we got a SIGINT or SIGTERM)
78 
79     // Block until all the threads exit
80     for(auto& t : v)
81         t.join();
82 
83     return EXIT_SUCCESS;
84 }
85