#include <iostream>
#include <thread>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/array.hpp>
#include <boost/algorithm/string.hpp>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
using websocketpp::server;
class WebSocketServer {
public:
    WebSocketServer()
        : server_()
    {
        server_.set_message_handler(bind(&WebSocketServer::on_message, this, ::_1, ::_2));
    }
    void run(uint16_t port) {
        server_.init_asio();
        // Set up the thread pool.
        boost::thread_group threads;
        for (std::size_t i = 0; i < boost::thread::hardware_concurrency(); ++i) {
            threads.create_thread(bind(&asio::io_service::run, &server_.get_io_service()));
        }
        // Start the server.
        server_.listen(port);
        server_.start_accept();
        std::cout << "WebSocket server listening on port " << port << "." << std::endl;
        // Wait for all threads in the pool to exit.
        threads.join_all();
    }
    void on_message(websocketpp::connection_hdl hdl, server::message_ptr msg) {
        server_.send(hdl, msg->get_payload(), msg->get_opcode());
    }
private:
    server server_;
};
int main(int argc, char* argv[]) {
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <port>" << std::endl;
        return 1;
    }
    uint16_t port = std::atoi(argv[1]);
    try {
        WebSocketServer server;
        server.run(port);
    } catch (std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
    return 0;
}