mercredi 6 janvier 2016

Why does my ASIO async_write timeout?

I am writing a C++11 application on Visual Studio 2015, and I use ASIO (not with boost). I followed the example in the server file, but changed all boost code to C++11.

The code works with a client which can connect and get the data. I modified the server code to use different timer for read and write. I also removed all the udp broadcast codes.

Code

void start() {
    std::cout << std::endl << "TCP Session start called " << 
        "read timeout = "<<&readTimeout_<<" write timeout = "<<&writeTimeout_<<std::endl;

    std::string firstPacket = process(input_buffer_);   // at this time, we require the process to judge
    deliver(firstPacket);
    await_output();

    output_deadline_.async_wait(
        std::bind(&TCP_Session::check_deadline, shared_from_this(), &output_deadline_)
        );

    start_read();

    input_deadline_.async_wait(
        std::bind(&TCP_Session::check_deadline, shared_from_this(), &input_deadline_)
        );
}
void deliver(const std::string& msg) {
    output_queue_.push_back(msg + "\n"+endChar);
    std::cout << "delivered one" << std::endl;
    // Signal that the output queue contains messages. Modifying the expiry
    // will wake the output actor, if it is waiting on the timer.
    non_empty_output_queue_.expires_at(std::chrono::high_resolution_clock::time_point::min());
}
void await_output() {
    if (stopped())
        return;

    if (output_queue_.empty()) {
    //  There are no messages ready to be sent. The actor goes to sleep by waiting on the non_empty_output_queue_ timer.
    //  When a new message is added, the timer will be modified and the actor will wake.
        non_empty_output_queue_.expires_at(std::chrono::high_resolution_clock::time_point::max());
        non_empty_output_queue_.async_wait(
            std::bind(&TCP_Session::await_output, shared_from_this()));
    } else {
        start_write();
    }
}

void start_write() {
    // Set a deadline for the write operation.
    output_deadline_.expires_from_now(writeTimeout_);

    // Start an asynchronous operation to send a message.
    asio::async_write(socket_,
        asio::buffer(output_queue_.front()),
        std::bind(&TCP_Session::handle_write, shared_from_this(), std::placeholders::_1));
}

void handle_write(const asio::error_code& ec) {
    if (stopped())
        return;

    if (!ec) {
        output_queue_.pop_front();
        await_output();
    } else {
        std::cout << "error when write ec=" << ec << std::endl;
        stop();
    }
}
std::chrono::milliseconds readTimeout_ = std::chrono::milliseconds(600000); //C++11 style
std::chrono::milliseconds writeTimeout_ = std::chrono::milliseconds(3000);  //C++11 style

Question

If the client connects, and doesn't send anything to server for 3 seconds, the server timeout. I know I put 3 seconds there for the writeTimeout_, but shouldn't it timeout when the write is not successful? My client can see the packet sent by the server.

Since I modified the original code and removed the udp part, should I remove the timeout for sending packet? Or should I adjust the timer after the async_write is successful?

Aucun commentaire:

Enregistrer un commentaire