ASIO async_read doesn't work while async_read_

2019-09-06 16:03发布

问题:

Observation

I built a demo application according to this server example using ASIO after I used C++11 std to replace everything originally in boost. The server can show that class member tcp_session::start() is called only after the client connects which is good indication that the server accepts the connection from the client.

However, I saw nothing received by handle_read while the clients sends a lot of data. I got some std::cout in handle_read and stop. I put the timeout to be 6 seconds now and found this: The start is called right after the client connects, and then nothing indicating that the handle_read is called, but after 6 seconds, stop() is called, and then handle_read is called because of the timeout and socket_.isOpen() is false.

Then I found that if I change async_read to async_read_until that was commented originally by me, then the handle_read will be called andthe socket_.isopen is true so I can really see the packets.

Question:

The delimiter was there but I don't want one. How do I async read a whole TCP string without a delimiter? Why async_read doesn't work? Should it work like this? Is there anything wrong in my code?

I am using VS2015 and test on localhost.

Answer

TCP doesn't have boundary so I decided to put special character to indicate the end of each packet.

Here are some relevant code:

class tcp_session : public subscriber, public  std::enable_shared_from_this<tcp_session> {
public:
void start() {
    std::cout<<"started"<<std::endl;
    channel_.join(shared_from_this());
    start_read();
    input_deadline_.async_wait(
        std::bind(&tcp_session::check_deadline, shared_from_this(), &input_deadline_)
        );
    await_output();

    output_deadline_.async_wait(
        std::bind(&tcp_session::check_deadline, shared_from_this(), &output_deadline_)
    );
}
private:    
bool stopped() const {
    return !socket_.is_open();// weird that it is still not open
}
void start_read() {

    // Set a deadline for the read operation.
    input_deadline_.expires_from_now(timeout_); //was std::chrono::seconds(30) in example
    char a = 0x7F;
    // Start an asynchronous operation to read a 0x7F-delimited message or read all
    //asio::async_read_until(socket_, input_buffer_, a, std::bind(&TCP_Session::handle_read, shared_from_this(), std::placeholders::_1));

    asio::async_read(socket_, input_buffer_, 
            std::bind(&TCP_Session::handle_read, shared_from_this(), std::placeholders::_1));
}
void handle_read(const asio::error_code& ec) {
    if (stopped()) // it thinks it stopped and returned without processing
        return;