0

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. Finally, I found that the stopped() is always true, which means the socket_.isOpen is false.

Question:

So I wonder whether I need to do anything to set the socket_ to be isOpen in start(), or the socket_ should be "Open" automatically (means connected)? Or is my understanding or assumption wrong?

I am using VS2015 and test on localhost.

Possibility:

I changed the default 30s timeout to 1 second. So while the server is connected, and before the client sends out data, is it possible the server timeout and closed the socket?

Update

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.

I am guessing the handlers were configured wrong.

Finding

Then I found that if I change async_read to async_read_until that was commented originally by me, then the handle_read will proceed because the socket_.isopen is true.

Therefore, the conclusion is, async_read can't get the handle_read to be called, but async_read_until can, and this becomes another question. The socket_.is_open() is true before the timeout stops the session.

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;
Community
  • 1
  • 1
Splash
  • 1,288
  • 2
  • 18
  • 36

1 Answers1

2

An open socket implies nothing about the state of its connection, and the state of a connection does not affect the open or closed state of a socket. The only guarantee between the two is that a closed socket has no connection.

Example client flow:

using boost::asio::ip::tcp;
tcp::socket socket(io_service);                   // closed state -- no connection
socket.open(...);                                 // opened state -- no connection
socket.bind(...);
socket.connect(...);                              // opened state -- connection
... connection established ...
... remote peer terminates/closes connection ...  // opened state -- no connection
assert(socket.is_open()); 
socket.close();                                   // closed state -- no connection
assert(!socket.is_open());

Example server flow:

using boost::asio::ip::tcp; 
tcp::acceptor acceptor_(io_service);              // acceptor closed state
acceptor.open(...);                               // acceptor opened state
acceptor.bind(...);
acceptor.listen();                                // acceptor listening state

tcp::socket socket(io_service);                   // closed state -- no connection
acceptor.accept(socket);                          // opened state -- connection
... connection established ...
... remote peer terminates/closes connection ...  // opened state -- no connection
assert(socket.is_open());
socket.close();                                   // closed state -- no connection
assert(!socket.is_open());

assert(acceptor.is_open();
acceptor.close();                                 // acceptor closed state
assert(!acceptor.is_open());

In your server, as socket_.is_open() is returning false, then socket_.close() was explicitly called on the socket within tcp_session::stop(). To get more insight into why it is being invoked, consider:

  • Defining BOOST_ASIO_ENABLE_HANDLER_TRACKING to enable handler tracking. When this is defined, Boost.Asio writes information about asynchronous operations and handler relationships to the standard error stream.
  • Attaching a debugger and setting a break point in tcp_session::stop().
Tanner Sansbury
  • 51,153
  • 9
  • 112
  • 169
  • Thanks. But could you describe a server side flow instead of client side? – Splash Dec 04 '15 at 16:49
  • @Splash I have updated the answer to show an example of a server-side flow. The same rules hold true: an open socket implies nothing about the state of its connection. – Tanner Sansbury Dec 04 '15 at 17:11
  • Awesome. I updated my post as well, because if I change async_read to async_read_until(..., 0x7F, ..) and it works, although all data is received, not delimited by 0x7F at all. – Splash Dec 04 '15 at 17:26
  • @Splash Adding details to provide additional context for a question can be helpful, but please avoid changing the question itself (e.g. socket/connection states to async reading without a delimiter). Instead, consider searching if the new question already exists, and if not, create a new question with a [mcve] and linking back to the original question. – Tanner Sansbury Dec 04 '15 at 17:43
  • Thanks. The question is considered closed since is_open() is true, and I moved to another question. – Splash Dec 04 '15 at 18:05