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