c++ - Boost asio io_content 运行非阻塞

标签 c++ boost boost-asio blocking boost-beast

<分区>

目前我正在编写一个 C++ Websocket 客户端库,它被封装在一个 C# 库中。
我正在使用 Boost Beast 进行 websocket 连接。
现在我在握手完成时启动 async_read,这样 websocket 就不会断开连接。
问题是 io_content 阻塞线程,因此 C# 程序停止执行,直到 async_read 超时并且 io_content 返回。但我希望 C# 程序继续执行。
我试图在一个线程中执行连接函数,但问题是,C# 程序调用的下一个函数是写操作,它崩溃了,因为连接函数仍在连接...

库.cpp:

void OpenConnection(char* id)
{
    std::cout << "Opening new connection..." << std::endl;
    std::shared_ptr<Session> session = std::make_shared<Session>();
    session->connect();
    sessions.emplace(std::string(id), std::move(session));
}

session .cpp:

void Session::connect()
{
    resolver.async_resolve(
        "websocket_uri",
        "443",
        beast::bind_front_handler(
            &Session::on_resolve,
            shared_from_this()));
    ioc.run();
}

on_resolve、on_connect、on_handshake...与此处相同:https://www.boost.org/doc/libs/1_70_0/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp

除非on_handshake函数:

void Session::on_handshake(beast::error_code ec)
{
    if (ec)
        return fail(ec, "handshake");

    ws.async_read(buffer, beast::bind_front_handler(&Session::on_read, shared_from_this()));
}

还有 on_read 函数:

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

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

    std::cout << "Got message" << std::endl;
    onMessage(Message::parseMessage(beast::buffers_to_string(buffer.data())));
    ws.async_read(buffer, beast::bind_front_handler(&Session::on_read, shared_from_this()));
}

还有 on_write 函数:

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

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

    queue.erase(queue.begin());

    if (!queue.empty())
    {
        ws.async_write(net::buffer(queue.front()->toString()), beast::bind_front_handler(&Session::on_write, shared_from_this()));
    }
}

C#程序(用于测试):

[DllImport(@"/data/cpp_projects/whatsapp_web_library/build/Debug/libWhatsApp_Web_Library.so")]
public static extern void OpenConnection(string id);
[DllImport(@"/data/cpp_projects/whatsapp_web_library/build/Debug/libWhatsApp_Web_Library.so")]
public static extern void CloseConnection(string id);
[DllImport(@"/data/cpp_projects/whatsapp_web_library/build/Debug/libWhatsApp_Web_Library.so")]
public static extern void GenerateQRCode(string id);

static void Main(string[] args)
{
   string id = "test";
   OpenConnection(id);
   GenerateQRCode(id);
}

现在是我的问题,我该如何实现它?
我已经在这个问题上停留了 3 天了,并且慢慢地感到绝望。

已经谢谢了:)

最佳答案

您需要使用async_read_some 而不是async_read

来自 boost

async_read_some function is used to asynchronously read data from the stream socket. The function call always returns immediately.

The read operation may not read all of the requested number of bytes. Consider using the async_read function if you need to ensure that the requested amount of data is read before the asynchronous operation completes.

基本上,成功调用 async_read_some 可能只读取一个字节, 或者它可能填满整个缓冲区,或介于两者之间的任何地方。这 另一方面,asio::async_read 函数可用于确保整个 缓冲区在操作完成之前被填满。 async_write_someasio::async_write 函数具有相同的关系。

More about async_read_some

这是一个很好的example如何使用 async_read_some

关于c++ - Boost asio io_content 运行非阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59619047/

相关文章:

c++ - 如何将 FASM 变量导出到 VC++ Express 2012?

c++ - 段错误,需要帮助读取核心转储

c++ - 创建大量文件后,fopen失败并显示EFBIG “File too large”

gcc - 如何在autoconf配置脚本/makefile中添加到库的链接

c++ - 什么是 c# AutoResetEvent/ManualResetEvent 的 c++ 可移植模拟?

c++ - 在带有 boost::function 的 std::for_each 中使用 boost.lambda

c++ - 如何使用 boost::asio::serial_port 支持硬件流控制?

c++ - "Objective C"与 "C++": difference in statement for method invocation

c++ - 使用 Boost 基本截止时间计时器来调用类方法

c++ - Boost asio接收指定大小的数据