如何在使用 boost websocket_server_async 方法时使 aync_read 和 async_write 彼此独立?

问题描述 投票:0回答:1

我在我的项目中使用 boost websocket 并坚持使用这段代码,其中我的 async_write 仅当它从客户端读取某些内容时才执行。

我使用了来自 websocket_server_async

的代码

下面是代码

void do_read()
{
    // 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);

    // This indicates that the session was closed
    if(ec == websocket::error::closed)
    return;

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

    // Echo the message
    ws_.text(ws_.got_text());
    ws_.async_write(
        buffer_.data(),
        beast::bind_front_handler(
            &session::on_write,
            shared_from_this()));
}

这里,由于 async_write 是在

on_read
函数中编写的,因此仅当从客户端发送某些内容时才会执行。但是我怎样才能不依赖于读取执行而连续向客户端写入消息

我尝试添加一个写入标志(每当需要向客户端发送数据时)并仅使用

ws_.write
代替
asyn_write
(这是正确的方法吗)。

void do_read()
{
    // Read a message into our buffer
    ws_.async_read(
        client_buffer_,
        beast::bind_front_handler(
            &session::on_read,
            shared_from_this()));
    if(write_flag)
    {
        do_write();
    }
}

void do_write()
{
    ws_.write(net::buffer(server_buffer_));
    write_flag = false;

    //Do another read
    do_read();
}

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

    // This indicates that the session was closed
    if(ec == websocket::error::closed)
        return;

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

    //Do another read
    do_read();
}
websocket boost boost-asio
1个回答
0
投票

你想让它独立。添加写入标志确实没有帮助。

而是让它字面上独立:

do_read_loop() {
     async_read(ws_, buf_, [this, self=shared_from_this](error_code ec, size_t bytes_transferred) {
         // ...
         if (!ec)
             do_read_loop();
     });
}

在写入方面,您希望相同,只是有时可能没有任何内容可发送。

std::deque<std::string> outbox_;

do_write_loop() {
     if (outbox_.empty())
         return;

     async_write(ws_, asio::buffer(outbox_.front()), [this, self=shared_from_this](error_code ec, size_t bytes_transferred) {
         // ...
         if (!ec) {
             outbox_.pop_front();
             do_write_loop();
         }
     });
}

就是这样。它几乎完全对称,并且完全独立。唯一缺少的部分是何时启动写循环。

 void send(std::string message) {
      outbox_.push_back(std::move(message));
      if (outbox_.size() == 1)
          do_write_loop();
 }

为了简单起见,我省略了股线(你的问题也没有提到它们)。如果您需要它们,您必须确保相关操作已完成:

    void send(std::string msg) {
        asio::post(ws_.get_executor(),
             [this, self = shared_from_this(), m = std::move(msg)]() mutable { do_send(std::move(m)); });
    }
© www.soinside.com 2019 - 2024. All rights reserved.