Сбой блокировки мьютекса Boost Websockets при реализации с использованием статических методов

Проблема

Я пытаюсь создать веб-сокет для подключения к довольно загруженному каналу сервера, используя C++ и Boost::Beast. На данный момент все, что он делает, это считывает данные, странным образом декодирует их и распечатывает.

У меня есть настройка, но по какой-то причине, когда я меняю настройку сокета, чтобы использовать статические методы и переменные в моем классе connection, это дает эту странную ошибку:

libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: mutex lock failed: Invalid argument

Что я сделал до сих пор

Поиск этой проблемы в Интернете, несколько потоки, похоже, намекают на то, что это проблема многопоточности. Дело в том, что мое программное обеспечение является однопоточным.

Все, что он делает до сих пор, это следующее:

main.cpp

#include "OkexSocket.h"

int main() {
    const std::string host = "real.okex.com";
    auto const port  = "8443";
    auto const path  = "/ws/v3";
    OkexSocket::init_socket(host, port, path);

    OkexSocket::send_subscribe(R"({"op": "subscribe", "args": ["swap/depth_l2_tbt:ETH-USDT-SWAP","swap/depth_l2_tbt:BTC-USDT-SWAP"]})");
    OkexSocket::receive_data();
}

и вот как я реализовал эти функции:

Сначала я создаю соединение через веб-сокет в OkexSocket::init_socket и сохраняю поток для последующего использования:

void OkexSocket::init_socket(const string& host, const string& port, const string& path) {
        net::io_context ioc;
        tcp::resolver resolver{ ioc };

        ssl::context ctx { ssl::context::sslv23 };
        ctx.set_verify_mode(ssl::verify_none);

        auto* socket = new websocket::stream<ssl::stream<tcp::socket>>{ioc, ctx };

        net::connect(beast::get_lowest_layer(*socket), resolver.resolve(host, port));

        // SSL handshake
        socket->next_layer().handshake(ssl::stream_base::client);

        socket->handshake(host + ":" + port, path);
        socket_logger->info("Client is connected...");
        OkexSocket::s = socket;
}

Затем я вызываю OkexSocket::send_subscribe, который в основном однострочный:

void OkexSocket::send_subscribe(const string &message) {
    // send request to the websocket
    s->write(net::buffer(message));
}

а затем я подаю поток данных так:

void OkexSocket::receive_data() {
    std::vector<uint8_t> in, out;
    auto in_buffer = net::dynamic_buffer(in);
    int i = 0;
    while (true) {
        socket->read(in_buffer);
        
        // decode and print in_buffer...

        in_buffer.consume(in_buffer.size());
        if (i++ == 300) {
            break;
        }
    }
}

Примечания и выводы...

  • да, я знаю, что есть утечка памяти, с OkexSocket::s. Меня это не волнует, поскольку оно должно существовать на протяжении всей жизни программы и инициализируется только один раз. Поскольку система вернет это пространство после того, как код будет выполнен, мне все равно. Однако открыт для критики по структуре кода.

  • Если вы добавите весь этот код в main(), он отлично заработает... не знаю, почему

Я довольно новичок в boost::beast, и я не нашел много ресурсов, чтобы помочь с этим :/ Я честно думаю, что документация предполагает кого-то, кто является профессионалом в boost и сетях, что, к сожалению, не так. Если все, что вы можете предоставить, это ресурсы, чтобы помочь мне, я был бы очень рад.


person QuantumHoneybees    schedule 23.02.2021    source источник
comment
Прошло некоторое время, но я считаю, что из-за того, что вы создаете буфер, который выходит за рамки в receive_data, это проблема. Я думаю, что буферы должны пережить соединения. Попробуйте сделать свой буфер членом вашего класса. Ваша ссылка   -  person lakeweb    schedule 23.02.2021