3

I am using a timer and an async_read, so whenever the timer runs out it cancels the async_read by doing ws_.next_layer().cancel() so that i can continue with my next operation. but when I catch the timeout error and continue the next write opertaion ws_.write() I get an operation cancelled error. Does the ws_.next_layer().cancel() make the socket unusable for subsequent operations. Is there any other alternate way to capture an idle timeout and quit from an async_read, while still keeping the socket functional without closing and reconnecting it.

#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;
    }
}

Iam trying to implement a idle timeout so the code exits from an infinite loop of async_read

1 Answer 1

0

Does the ws_.next_layer().cancel()

You'd have to assume as much. The docs say e.g.

Per-Operation Cancellation

This asynchronous operation supports cancellation for the following net::cancellation_type values:

  • net::cancellation_type::terminal
  • net::cancellation_type::total

total cancellation succeeds if the operation is suspended due to ongoing control operations such as a ping/pong.

terminal cancellation succeeds when supported by the underlying stream.

terminal cancellation leaves the stream in an undefined state, so that only closing it is guaranteed to succeed.

Since you cannot guarantee total cancellation, you have to assume terminal cancellation, which means that you can only close the transport.

Ideas

You should probably implement application logic in the application layer. E.g. have an outgoing queue and stop the writeloop instead of hard-cancelling operations on the underlying stream.

Sign up to request clarification or add additional context in comments.

7 Comments

Is there any other library that supports timeout inherently, cause iam only looking to write a demonstration code. ps any easy websocket library in cpp
I'm confused, in what way do you want to "while still keeping the socket functional without closing and reconnecting it"? Just don't cancel the read then. You can of course return timeout without canceling the read, but still the next read will read the first incoming message so depending on your protocol it might not make any sense without reconnecting
So basically if the socket idles out, no messages to read for a 3 second duration ,I want to come out of the read loop and continue with the next operation.
What is the next operation? And if you will never read again, why not just leave the read but ignore it if it happens after your deadline? No cancel, no problem.
Yes, I have realized it now will follow your recommendation. Thank you so much for patiently answering my questions.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.