Asio end socket functions: cancel, shutdown, close, release
Asked Answered
K

1

7

Which is the correct way to close and clean up a socket?

I have the io_service running in a secondary thread and I need to close the connection from the main thread:

void closeConnection()
{
    ioc.post([&socket]() {
        // Which ones do I have to call?
        // In what order?
        // What do they do?
        //socket.cancel();
        //socket.shutdown(asio::ip::tcp::socket::shutdown_both);
        //socket.close();
        //socket.release();
    });
    secondaryThread.join();
}

What is the difference between all these functions?

I've tried with this sequence ...

socket.cancel();
socket.close();
socket.release();

and seems to close up the connection without errors but takes too much time (about 5-10 seconds), so I guess I'm doing something wrong.

Komatik answered 22/7, 2018 at 20:6 Comment(1)
It turned out there was a silly mistake in my code. In the function that handles read_async I was posting another read_async even if the error code was false. Still think it would be interesting to have a clarification of what all these functions do.Komatik
H
11

I presume you're talking about a graceful close, i.e. read/write any outstanding data, then close the socket.

The proper steps are:

  1. Call shutdown() to indicate that you will not write any more data to the socket.

  2. Continue to (async-) read from the socket until you get either an error or the connection is closed.

  3. Now close() the socket (in the async read handler).

If you don't do this, you may end up closing the connection while the other side is still sending data. This will result in an ungraceful close.


cancel() and release() aren't the calls you use in a normal flow:

  • cancel() cancels all outstanding asynchronous operations.
  • release() releases ownership of the underlying native socket.
Hunsinger answered 22/7, 2018 at 20:45 Comment(5)
My application is a chat client, it is waiting for async read, wouldn't it get stuck in 2? I could cancel the async_read with cancel()? Thanks!Komatik
That's what shutdown() is for - it will cause any in-progress async read to finish with a "socket closed" error, at which point you can close() the socket.Hunsinger
Ok, so if I understand correctly, shutdown does everything cancel does plus doesn't allow for future operations?Komatik
@Komatik Not really. The shutdown function initiates the closure of the socket. Outstanding reads might complete if the other side sends you data. The cancel function cancels outstanding async operations, which leaves a mess. Say there's data in flight to you at the time -- if you cancel the outstanding async operations, how will you receive that data?Antedate
Ah, I see. Thanks a lot!Komatik

© 2022 - 2024 — McMap. All rights reserved.