i cannot build one of the examples provided in the beast websocket example

508 views Asked by At

My code :

#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/strand.hpp>
#include <boost/thread/thread.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <cstdlib>
#include <fstream>
#include <jsoncpp/json/value.h>
#include <jsoncpp/json/json.h>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include<unistd.h>
#include<sys/types.h>
using namespace std;

namespace beast = boost::beast;         // from <boost/beast.hpp>
namespace http = beast::http;           // from <boost/beast/http.hpp>
namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
namespace net = boost::asio;            // from <boost/asio.hpp>
using tcp = boost::asio::ip::tcp;       // from <boost/asio/ip/tcp.hpp>


//------------------------------------------------------------------------------

// Report a failure
void
fail(beast::error_code ec, char const* what)
{
    std::cerr << what << ": " << ec.message() << "\n";
}

// Sends a WebSocket message and prints the response
class session : public std::enable_shared_from_this<session>
{
    tcp::resolver resolver_;
    websocket::stream<beast::tcp_stream> ws_;
    beast::flat_buffer buffer_;
    std::string host_;
    Json::Value json;

public:
    // Resolver and socket require an io_context
    explicit
    session(net::io_context& ioc)
        : resolver_(net::make_strand(ioc))
        , ws_(net::make_strand(ioc))
    {
    }

    // Start the asynchronous operation
    void
    run(
        char const* host,
        char const* port,
        Json::Value text)
    {
        // Save these for later
        host_ = host;
        json = text;

        // Look up the domain name
        resolver_.async_resolve(
            host,
            port,
            beast::bind_front_handler(
                &session::on_resolve,
                shared_from_this()));
    }

    void
    on_resolve(
        beast::error_code ec,
        tcp::resolver::results_type results)
    {
        if(ec)
            return fail(ec, "resolve");

        // Set the timeout for the operation
        beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));

        // Make the connection on the IP address we get from a lookup
        beast::get_lowest_layer(ws_).async_connect(
            results,
            beast::bind_front_handler(
                &session::on_connect,
                shared_from_this()));
    }

    void
    on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep)
    {
        if(ec)
            return fail(ec, "connect");

        // Turn off the timeout on the tcp_stream, because
        // the websocket stream has its own timeout system.
        beast::get_lowest_layer(ws_).expires_never();

        // Set suggested timeout settings for the websocket
        ws_.set_option(
            websocket::stream_base::timeout::suggested(
                beast::role_type::client));

        // Set a decorator to change the User-Agent of the handshake
        ws_.set_option(websocket::stream_base::decorator(
            [](websocket::request_type& req)
            {
                req.set(http::field::user_agent,
                    std::string(BOOST_BEAST_VERSION_STRING) +
                        " websocket-client-async");
            }));

        // Update the host_ string. This will provide the value of the
        // Host HTTP header during the WebSocket handshake.
        // See https://tools.ietf.org/html/rfc7230#section-5.4
        host_ += ':' + std::to_string(ep.port());

        // Perform the websocket handshake
        ws_.async_handshake(host_, "/",
            beast::bind_front_handler(
                &session::on_handshake,
                shared_from_this()));
    }

    std::string 
    Json_to_string(const Json::Value &json)
    {
        std::string result;
        Json::StreamWriterBuilder wbuilder;

        wbuilder["indentation"] = "";       // Optional
        result = Json::writeString(wbuilder, json);
        return result;
    }

    void
    on_handshake(beast::error_code ec)
    {
        if(ec)
            return fail(ec, "handshake");
        
        // Send the message
        std::string jsonner = Json_to_string(json);
        auto jsontxt = std::make_shared<std::string>(jsonner);

        ws_.async_write(
            boost::asio::buffer(*jsontxt),
            beast::bind_front_handler(
                &session::on_write,
                shared_from_this(),jsontxt));
    }

    void
    on_write(
        beast::error_code ec,
        std::size_t bytes_transferred)
    {
        boost::ignore_unused(bytes_transferred);

        if(ec)
            return fail(ec, "write");
        
        // Read a message into our buffer
        ws_.async_read(
            buffer_,
            beast::bind_front_handler(
                &session::on_read,
                shared_from_this()));
    }

    void
    on_read(
        beast::error_code ec,
        std::size_t bytes_transferred)
    {
        boost::ignore_unused(bytes_transferred);

        if(ec)
            return fail(ec, "read");

        // Close the WebSocket connection
        ws_.async_close(websocket::close_code::normal,
            beast::bind_front_handler(
                &session::on_close,
                shared_from_this()));
    }

    void
    on_close(beast::error_code ec)
    {
        if(ec)
            return fail(ec, "close");

        // If we get here then the connection is closed gracefully

        // The make_printable() function helps print a ConstBufferSequence
        std::cout << beast::make_printable(buffer_.data()) << std::endl;
    }
};

//------------------------------------------------------------------------------

int main(int argc, char** argv)
{
    // Check command line arguments.
    if(argc != 4)
    {
        std::cerr <<
            "Usage: websocket-client-async <host> <port> <text>\n" <<
            "Example:\n" <<
            "    websocket-client-async echo.websocket.org 80 \"Hello, world!\"\n";
        return EXIT_FAILURE;
    }
    // auto const host = argv[1];
    // auto const port = argv[1];
    // auto const text = argv[1];

    ifstream file("details.json");
    Json::Value actualjson;
    Json::Reader jsonreader;

    jsonreader.parse(file,actualjson);

    // The io_context is required for all I/O
    net::io_context context;

    // Launch the asynchronous operation
    std::make_shared<session>(context)->run("stream.binance.com","9443", actualjson);

    // Run the I/O service. The call will return when
    // the socket is closed.
    context.run();

    return EXIT_SUCCESS;
}

Full error in a gist, abbreviated:

In file included from /usr/include/boost/beast/core/bind_handler.hpp:14,
                 from /usr/include/boost/beast/core/async_base.hpp:14,
                 from /usr/include/boost/beast/core.hpp:15,
                 from /home/user/Desktop/HFTBOT/src/main.cpp:1:
/usr/include/boost/beast/core/detail/bind_handler.hpp: In instantiation of ‘void boost::beast::...
/usr/include/boost/beast/core/detail/bind_handler.hpp:258:9:   required from ‘void boost::beast...
/usr/include/boost/beast/core/async_base.hpp:353:13:   required from ‘void boost::beast::async_...
/usr/include/boost/beast/websocket/impl/write.hpp:167:59:   required from ‘void boost::beast::w...
/usr/include/boost/beast/websocket/impl/write.hpp:140:16:   required from ‘boost::beast::websoc...
/usr/include/boost/beast/websocket/impl/write.hpp:459:9:   required from ‘void boost::beast::we...
/usr/include/boost/asio/async_result.hpp:82:49:   required from ‘static boost::asio::async_resu...
/usr/include/boost/asio/async_result.hpp:257:25:   required from ‘typename std::enable_if<boost...
/usr/include/boost/beast/websocket/impl/write.hpp:772:39:   required from ‘typename boost::asio...
/home/user/Desktop/HFTBOT/src/main.cpp:153:44:   required from here
/usr/include/boost/beast/core/detail/bind_handler.hpp:235:24: error: no match for call to ‘(std...
  235 |         std::mem_fn(h_)(
      |         ~~~~~~~~~~~~~~~^
  236 |             detail::get<I>(std::move(args_))...,
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  237 |             std::forward<Ts>(ts)...);
      |             ~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/system/error_code.hpp:19,
                 from /usr/include/boost/beast/core/error.hpp:14,
                 from /usr/include/boost/beast/core/detail/bind_handler.hpp:13,
                 from /usr/include/boost/beast/core/bind_handler.hpp:14,
                 from /usr/include/boost/beast/core/async_base.hpp:14,
                 from /usr/include/boost/beast/core.hpp:15,
                 from /home/user/Desktop/HFTBOT/src/main.cpp:1:
/usr/include/c++/9/functional:110:2: note: candidate: ‘template<class ... _Args> decltype (std:...
  110 |  operator()(_Args&&... __args) const
      |  ^~~~~~~~
/usr/include/c++/9/functional:110:2: note:   template argument deduction/substitution failed:
/usr/include/c++/9/functional: In substitution of ‘template<class ... _Args> decltype (std::__i...
/usr/include/boost/beast/core/detail/bind_handler.hpp:235:24:   required from ‘void boost::beas...
/usr/include/boost/beast/core/detail/bind_handler.hpp:258:9:   required from ‘void boost::beast...
/usr/include/boost/beast/core/async_base.hpp:353:13:   required from ‘void boost::beast::async_...
/usr/include/boost/beast/websocket/impl/write.hpp:167:59:   required from ‘void boost::beast::w...
/usr/include/boost/beast/websocket/impl/write.hpp:140:16:   required from ‘boost::beast::websoc...
/usr/include/boost/beast/websocket/impl/write.hpp:459:9:   required from ‘void boost::beast::we...
/usr/include/boost/asio/async_result.hpp:82:49:   required from ‘static boost::asio::async_resu...
/usr/include/boost/asio/async_result.hpp:257:25:   required from ‘typename std::enable_if<boost...
/usr/include/boost/beast/websocket/impl/write.hpp:772:39:   required from ‘typename boost::asio...
/home/user/Desktop/HFTBOT/src/main.cpp:153:44:   required from here
/usr/include/c++/9/functional:113:27: error: no matching function for call to ‘__invoke(void (s...
  113 |  -> decltype(std::__invoke(_M_pmf, std::forward<_Args>(__args)...))
      |              ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/tuple:41,
                 from /usr/include/c++/9/functional:54,
                 from /usr/include/boost/system/error_code.hpp:19,
                 from /usr/include/boost/beast/core/error.hpp:14,
                 from /usr/include/boost/beast/core/detail/bind_handler.hpp:13,
                 from /usr/include/boost/beast/core/bind_handler.hpp:14,
                 from /usr/include/boost/beast/core/async_base.hpp:14,
                 from /usr/include/boost/beast/core.hpp:15,
                 from /home/user/Desktop/HFTBOT/src/main.cpp:1:
/usr/include/c++/9/bits/invoke.h:89:5: note: candidate: ‘template<class _Callable, class ... _A...
   89 |     __invoke(_Callable&& __fn, _Args&&... __args)
      |     ^~~~~~~~
/usr/include/c++/9/bits/invoke.h:89:5: note:   template argument deduction/substitution failed:...
/usr/include/c++/9/bits/invoke.h: In substitution of ‘template<class _Callable, class ... _Args...
/usr/include/c++/9/functional:113:27:   required by substitution of ‘template<class ... _Args> ...
/usr/include/boost/beast/core/detail/bind_handler.hpp:235:24:   required from ‘void boost::beas...
/usr/include/boost/beast/core/detail/bind_handler.hpp:258:9:   required from ‘void boost::beast...
/usr/include/boost/beast/core/async_base.hpp:353:13:   required from ‘void boost::beast::async_...
/usr/include/boost/beast/websocket/impl/write.hpp:167:59:   required from ‘void boost::beast::w...
/usr/include/boost/beast/websocket/impl/write.hpp:140:16:   required from ‘boost::beast::websoc...
/usr/include/boost/beast/websocket/impl/write.hpp:459:9:   required from ‘void boost::beast::we...
/usr/include/boost/asio/async_result.hpp:82:49:   required from ‘static boost::asio::async_resu...
/usr/include/boost/asio/async_result.hpp:257:25:   required from ‘typename std::enable_if<boost...
/usr/include/boost/beast/websocket/impl/write.hpp:772:39:   required from ‘typename boost::asio...
/home/user/Desktop/HFTBOT/src/main.cpp:153:44:   required from here
/usr/include/c++/9/bits/invoke.h:89:5: error: no type named ‘type’ in ‘struct std::__invoke_res...
In file included from /usr/include/boost/beast/core/bind_handler.hpp:14,
                 from /usr/include/boost/beast/core/async_base.hpp:14,
                 from /usr/include/boost/beast/core.hpp:15,
                 from /home/user/Desktop/HFTBOT/src/main.cpp:1:
/usr/include/boost/beast/core/detail/bind_handler.hpp: In instantiation of ‘void boost::beast::...
/usr/include/boost/beast/core/detail/bind_handler.hpp:258:9:   required from ‘void boost::beast...
/usr/include/boost/beast/core/detail/bind_handler.hpp:224:9:   required from ‘void boost::beast...
/usr/include/boost/beast/core/detail/bind_handler.hpp:258:9:   required from ‘void boost::beast...
/usr/include/boost/asio/bind_executor.hpp:414:61:   required from ‘typename std::result_of<T(Ar...
/usr/include/boost/asio/detail/executor_function.hpp:91:15:   required from ‘static void boost:...
/usr/include/boost/asio/detail/executor_function.hpp:66:50:   [ skipping 8 instantiation contex...
/usr/include/boost/beast/websocket/impl/write.hpp:140:16:   required from ‘boost::beast::websoc...
/usr/include/boost/beast/websocket/impl/write.hpp:459:9:   required from ‘void boost::beast::we...
/usr/include/boost/asio/async_result.hpp:82:49:   required from ‘static boost::asio::async_resu...
/usr/include/boost/asio/async_result.hpp:257:25:   required from ‘typename std::enable_if<boost...
/usr/include/boost/beast/websocket/impl/write.hpp:772:39:   required from ‘typename boost::asio...
/home/user/Desktop/HFTBOT/src/main.cpp:153:44:   required from here
/usr/include/boost/beast/core/detail/bind_handler.hpp:235:24: error: no match for call to ‘(std...
  235 |         std::mem_fn(h_)(
      |         ~~~~~~~~~~~~~~~^
  236 |             detail::get<I>(std::move(args_))...,
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  237 |             std::forward<Ts>(ts)...);
      |             ~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/system/error_code.hpp:19,
                 from /usr/include/boost/beast/core/error.hpp:14,
                 from /usr/include/boost/beast/core/detail/bind_handler.hpp:13,
                 from /usr/include/boost/beast/core/bind_handler.hpp:14,
                 from /usr/include/boost/beast/core/async_base.hpp:14,
                 from /usr/include/boost/beast/core.hpp:15,
                 from /home/user/Desktop/HFTBOT/src/main.cpp:1:
/usr/include/c++/9/functional:110:2: note: candidate: ‘template<class ... _Args> decltype (std:...
  110 |  operator()(_Args&&... __args) const
      |  ^~~~~~~~
/usr/include/c++/9/functional:110:2: note:   template argument deduction/substitution failed:
/usr/include/c++/9/functional: In substitution of ‘template<class ... _Args> decltype (std::__i...
/usr/include/boost/beast/core/detail/bind_handler.hpp:235:24:   required from ‘void boost::beas...
/usr/include/boost/beast/core/detail/bind_handler.hpp:258:9:   required from ‘void boost::beast...
/usr/include/boost/beast/core/detail/bind_handler.hpp:224:9:   required from ‘void boost::beast...
/usr/include/boost/beast/core/detail/bind_handler.hpp:258:9:   required from ‘void boost::beast...
/usr/include/boost/asio/bind_executor.hpp:414:61:   required from ‘typename std::result_of<T(Ar...
/usr/include/boost/asio/detail/executor_function.hpp:91:15:   [ skipping 9 instantiation contex...
/usr/include/boost/beast/websocket/impl/write.hpp:140:16:   required from ‘boost::beast::websoc...
/usr/include/boost/beast/websocket/impl/write.hpp:459:9:   required from ‘void boost::beast::we...
/usr/include/boost/asio/async_result.hpp:82:49:   required from ‘static boost::asio::async_resu...
/usr/include/boost/asio/async_result.hpp:257:25:   required from ‘typename std::enable_if<boost...
/usr/include/boost/beast/websocket/impl/write.hpp:772:39:   required from ‘typename boost::asio...
/home/user/Desktop/HFTBOT/src/main.cpp:153:44:   required from here
/usr/include/c++/9/functional:113:27: error: no matching function for call to ‘__invoke(void (s...
  113 |  -> decltype(std::__invoke(_M_pmf, std::forward<_Args>(__args)...))
      |              ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/tuple:41,
                 from /usr/include/c++/9/functional:54,
                 from /usr/include/boost/system/error_code.hpp:19,
                 from /usr/include/boost/beast/core/error.hpp:14,
                 from /usr/include/boost/beast/core/detail/bind_handler.hpp:13,
                 from /usr/include/boost/beast/core/bind_handler.hpp:14,
                 from /usr/include/boost/beast/core/async_base.hpp:14,
                 from /usr/include/boost/beast/core.hpp:15,
                 from /home/user/Desktop/HFTBOT/src/main.cpp:1:
/usr/include/c++/9/bits/invoke.h:89:5: note: candidate: ‘template<class _Callable, class ... _A...
   89 |     __invoke(_Callable&& __fn, _Args&&... __args)
      |     ^~~~~~~~
/usr/include/c++/9/bits/invoke.h:89:5: note:   template argument deduction/substitution failed:...
/usr/include/c++/9/bits/invoke.h: In substitution of ‘template<class _Callable, class ... _Args...
/usr/include/c++/9/functional:113:27:   required by substitution of ‘template<class ... _Args> ...
/usr/include/boost/beast/core/detail/bind_handler.hpp:235:24:   required from ‘void boost::beas...
/usr/include/boost/beast/core/detail/bind_handler.hpp:258:9:   required from ‘void boost::beast...
/usr/include/boost/beast/core/detail/bind_handler.hpp:224:9:   required from ‘void boost::beast...
/usr/include/boost/beast/core/detail/bind_handler.hpp:258:9:   required from ‘void boost::beast...
/usr/include/boost/asio/bind_executor.hpp:414:61:   [ skipping 10 instantiation contexts, use -...
/usr/include/boost/beast/websocket/impl/write.hpp:140:16:   required from ‘boost::beast::websoc...
/usr/include/boost/beast/websocket/impl/write.hpp:459:9:   required from ‘void boost::beast::we...
/usr/include/boost/asio/async_result.hpp:82:49:   required from ‘static boost::asio::async_resu...
/usr/include/boost/asio/async_result.hpp:257:25:   required from ‘typename std::enable_if<boost...
/usr/include/boost/beast/websocket/impl/write.hpp:772:39:   required from ‘typename boost::asio...
/home/user/Desktop/HFTBOT/src/main.cpp:153:44:   required from here
/usr/include/c++/9/bits/invoke.h:89:5: error: no type named ‘type’ in ‘struct std::__invoke_res...
make[2]: *** [CMakeFiles/hftbot.dir/build.make:83: CMakeFiles/hftbot.dir/src/main.cpp.o] Error ...
make[1]: *** [CMakeFiles/Makefile2:116: CMakeFiles/hftbot.dir/all] Error 2

So i am trying to send json request to binance for streaming market updates over the websocket. binance api docs : https://binance-docs.github.io/apidocs/spot/en/#websocket-market-streams

my details.json looks :

{
    "method": "SUBSCRIBE",
    "params":
    [
        "btcusdt@depth"
    ],
    "id": 1
}

I dont know what is happening here. Please help me and advance thanks!

1

There are 1 answers

0
sehe On BEST ANSWER

Here:

    auto jsontxt = std::make_shared<std::string>(jsonner);

    ws_.async_write(
        boost::asio::buffer(*jsontxt),
        beast::bind_front_handler(
            &session::on_write,
            shared_from_this(),jsontxt));

You have bound an extra argument jsontxt. The thinking is alright: you wanted to extend the lifetime of the json text buffer to the duration of the write operation. However on_write doesn't take that extra jsontxt argument.

You might fix that changing from

void on_write(beast::error_code ec, std::size_t bytes_transferred) {

to

void on_write(std::shared_ptr<std::string> /*jsontxt*/,
              beast::error_code ec, std::size_t bytes_transferred) {

That does compile. However, it's a bit clunky, it doesn't scale well (how many more arguments will you have bind into various handlers?). Can we do better?

Doing Better

Notice that the session class already uses shared ownership:

class session : public std::enable_shared_from_this<session>

Next, notice that you already share that ownership in the handler using shared_from_this() (instead of, e.g., just this).

This means that if you make jsontxt a member of the class you will already have the life-time guarantee, but more efficiently and without the clunkiness of using an extra bound argument.

In fact, you can then store the stringified JSON directly in run():

#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/strand.hpp>
#include <boost/thread/thread.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

#include <cstdlib>
#include <fstream>
#include <json/json.h>
#include <functional>
#include <iostream>
#include <memory>
#include <string>

#include <sys/types.h>
#include <unistd.h>

namespace beast     = boost::beast;     // from <boost/beast.hpp>
namespace http      = beast::http;      // from <boost/beast/http.hpp>
namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
namespace net       = boost::asio;      // from <boost/asio.hpp>
using tcp           = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>

//------------------------------------------------------------------------------

// Report a failure
void
fail(beast::error_code ec, char const* what)
{
    std::cerr << what << ": " << ec.message() << "\n";
}

// Sends a WebSocket message and prints the response
class session : public std::enable_shared_from_this<session>
{
    tcp::resolver                        resolver_;
    websocket::stream<beast::tcp_stream> ws_;

    beast::flat_buffer buffer_;
    std::string        host_;
    std::string        message_text_;

  public:
    // Resolver and socket require an io_context
    explicit
    session(net::io_context& ioc)
        : resolver_(net::make_strand(ioc))
        , ws_(net::make_strand(ioc))
    {
    }

    // Start the asynchronous operation
    void
    run(
        char const* host,
        char const* port,
        Json::Value message)
    {
        // Save these for later
        host_         = host;
        message_text_ = Json_to_string(message);

        // Look up the domain name
        resolver_.async_resolve(
            host,
            port,
            beast::bind_front_handler(
                &session::on_resolve,
                shared_from_this()));
    }

    void
    on_resolve(
        beast::error_code ec,
        tcp::resolver::results_type results)
    {
        if(ec)
            return fail(ec, "resolve");

        // Set the timeout for the operation
        beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));

        // Make the connection on the IP address we get from a lookup
        beast::get_lowest_layer(ws_).async_connect(
            results,
            beast::bind_front_handler(
                &session::on_connect,
                shared_from_this()));
    }

    void
    on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type ep)
    {
        if(ec)
            return fail(ec, "connect");

        // Turn off the timeout on the tcp_stream, because
        // the websocket stream has its own timeout system.
        beast::get_lowest_layer(ws_).expires_never();

        // Set suggested timeout settings for the websocket
        ws_.set_option(
            websocket::stream_base::timeout::suggested(
                beast::role_type::client));

        // Set a decorator to change the User-Agent of the handshake
        ws_.set_option(websocket::stream_base::decorator(
            [](websocket::request_type& req)
            {
                req.set(http::field::user_agent,
                    std::string(BOOST_BEAST_VERSION_STRING) +
                        " websocket-client-async");
            }));

        // Update the host_ string. This will provide the value of the
        // Host HTTP header during the WebSocket handshake.
        // See https://tools.ietf.org/html/rfc7230#section-5.4
        host_ += ':' + std::to_string(ep.port());

        // Perform the websocket handshake
        ws_.async_handshake(host_, "/",
            beast::bind_front_handler(
                &session::on_handshake,
                shared_from_this()));
    }

    std::string Json_to_string(const Json::Value& json) {
        Json::StreamWriterBuilder wbuilder;
        wbuilder["indentation"] = ""; // Optional
        return Json::writeString(wbuilder, json);
    }

    void
    on_handshake(beast::error_code ec)
    {
        if(ec) {
            return fail(ec, "handshake");
        }
        
        // Send the message
        ws_.async_write(
            net::buffer(message_text_),
            beast::bind_front_handler(&session::on_write, shared_from_this()));
    }

    void on_write(beast::error_code ec, std::size_t bytes_transferred) {
        boost::ignore_unused(bytes_transferred);

        if(ec)
            return fail(ec, "write");
        
        // Read a message into our buffer
        ws_.async_read(
            buffer_,
            beast::bind_front_handler(
                &session::on_read,
                shared_from_this()));
    }

    void
    on_read(
        beast::error_code ec,
        std::size_t bytes_transferred)
    {
        boost::ignore_unused(bytes_transferred);

        if(ec)
            return fail(ec, "read");

        // Close the WebSocket connection
        ws_.async_close(websocket::close_code::normal,
            beast::bind_front_handler(
                &session::on_close,
                shared_from_this()));
    }

    void
    on_close(beast::error_code ec)
    {
        if(ec)
            return fail(ec, "close");

        // If we get here then the connection is closed gracefully

        // The make_printable() function helps print a ConstBufferSequence
        std::cout << beast::make_printable(buffer_.data()) << std::endl;
    }
};

//------------------------------------------------------------------------------

int main()
{
    // auto const host = argv[1];
    // auto const port = argv[1];
    // auto const text = argv[1];

    std::ifstream file("details.json");
    Json::Value actualjson;
    Json::Reader jsonreader;

    jsonreader.parse(file,actualjson);

    // The io_context is required for all I/O
    net::io_context context;

    // Launch the asynchronous operation
    std::make_shared<session>(context)->run("stream.binance.com", "9443",
                                            actualjson);

    // Run the I/O service. The call will return when
    // the socket is closed.
    context.run();

    return EXIT_SUCCESS;
}