尝试通过取消当前的async_read并继续下一个读/写操作来实现空闲超时

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

我正在使用计时器和 async_read,因此每当计时器耗尽时,它就会通过执行 ws_.next_layer().cancel() 取消 async_read,以便我可以继续下一个操作。但是当我捕获超时错误并继续下一个写入操作 ws_.write() 时,我收到操作取消错误。 ws_.next_layer().cancel() 是否会使套接字无法用于后续操作。 是否有其他替代方法来捕获空闲超时并从 async_read 退出,同时仍然保持套接字功能而无需关闭并重新连接它。

#include "Socket_Factory_1.h"


class TimeoutException : public std::exception {
public:
    explicit TimeoutException(const std::string& message) : message_(message) {}
    
    virtual const char* what() const noexcept override {
        return message_.c_str();
    }

private:
    std::string message_;
};

WebSocketClient::WebSocketClient(const std::string& host, const std::string& port)
    : host_(host), port_(port), ioc_(), resolver_(ioc_), ws_(ioc_), timer_(ioc_) {}

WebSocketClient::~WebSocketClient() {
    close();
}

void WebSocketClient::connect() {
    try {
        ws_.binary(true);
        auto const results = resolver_.resolve(host_, port_);
        asio::connect(ws_.next_layer(), results.begin(), results.end());
        ws_.handshake(host_, "/");
    } catch (const std::exception& e) {
        std::cerr << "Connect Error: " << e.what() << std::endl;
        throw;
    }
}

void WebSocketClient::send(const void* data, size_t size) {
    try {
        ws_.write(asio::buffer(data, size));
    } catch (const std::exception& e) {
        std::cerr << "Send Error: " << e.what() << std::endl;
        throw;
    }
}

std::string WebSocketClient::receive() {
    std::cout<<"HI1";
    
        
        read_successful = false;
        timeout_occurred = false;

        // Set up the timer
        std::chrono::seconds timeout_duration(3);
        timer_.expires_after(timeout_duration);
        std::cout<<"HI";
        // Start an asynchronous read operation
        ws_.async_read(buffer,
            [this](beast::error_code ec, std::size_t bytes_transferred) {
                if (!ec) {
                    result = beast::buffers_to_string(buffer.data());
                    read_successful = true; // Mark read as successful
                } 
                else if(ec==asio::error::operation_aborted){
                    std::cout<<"aborted"<<std::endl;
                }
                else {
                    std::cerr << "Read Error: " << ec.message() << std::endl;
                }
            }
        );

        // Set up the timeout handler
        timer_.async_wait(
            [this](beast::error_code ec) {
                if (ec != asio::error::operation_aborted) {
                    timeout_occurred = true; // Mark timeout as occurred
                }else{

                    std::cout<<"aborted tiemr"<<std::endl;
                }
            }
        );

        // Run the IO context to perform the asynchronous operations
        while (!read_successful && !timeout_occurred) {
            ioc_.run_one(); // Process one ready handler
        }
        buffer.clear();
        if (timeout_occurred) {
            ws_.next_layer().cancel();
            ioc_.run();
            // ioc_.restart();
            std::cerr << "Read operation timed out\n";
            throw TimeoutException("Timeout");
        }
        if (read_successful) {
            timer_.cancel();
            return result;
        }
        return ""; // Return empty string if neither read nor timeout occurred
    }
void WebSocketClient::close() {
    try {
        if (ws_.is_open()) {
            ws_.close(websocket::close_code::normal);
        }
    } catch (const std::exception& e) {
        std::cerr << "Close Error: " << e.what() << std::endl;
    }
}

我正在尝试实现空闲超时,以便代码从 async_read 的无限循环中退出

boost boost-asio boost-beast boost-beast-websocket
1个回答
0
投票

ws_.next_layer().cancel()是否

你必须假设同样多的事情。文档说例如

每次操作取消

该异步操作支持取消以下操作

net::cancellation_type
值:

  • net::cancellation_type::terminal
  • 网络::取消类型::总计

如果因以下原因暂停操作,则完全取消成功 持续的控制操作,例如乒乓球。

底层支持时终端取消成功 流。

终端取消使流处于未定义状态,因此 只有关闭它才保证成功。

由于您不能保证全部取消,所以您必须假设终点站取消,这意味着您只能关闭运输。

想法

您可能应该在应用程序层实现应用程序逻辑。例如。有一个传出队列并停止写循环,而不是在底层流上硬取消操作。

© www.soinside.com 2019 - 2024. All rights reserved.