shb
shb

Reputation: 51

boost::asio: How to detect that the receiver socket is closed in async_write handler?

The implementation:

The client uses async_write to sending messages to the server. In the write handler, it starts next async_write operation.

The server uses async_read to receive messages from the client. In the read handler, it starts next async_read operation.

I want to stop the async operation immediately when the remote side is closed.

When I close the client, the async_read calls the handler immediately with an boost::asio::error::eof error code. But when the server is closed, the client continues writing. How can I make it call the handler with an error code?

Upvotes: 0

Views: 1187

Answers (2)

Jean Davy
Jean Davy

Reputation: 2240

You read/write, in other words you have a protocol, so add a new flag (message, bit ...) saying that you will close the socket, and close the socket only when that message has been received. Of course your protocol must handle errors.

Upvotes: 0

Tofu
Tofu

Reputation: 3613

In simple terms your design should look like this:

Call async_read

When you need to write

Call async_write

Do not call async_write again until the previous async_write call has returned. If you need to call multiple async_write operations, then que your buffers.

Call async_write
callback pull next buffer from que
Call async_write
callback pull next buffer from que
Call async_write
callback pull next buffer from que

By doing this, you're ensuring this only one async_write operating is in effect at all times per socket. Which is how it should be. Do NOT do this.

Call async_write
Call async_write
Call async_write
callback
callback
callback

This is where you run into issues by trying to stop async_write after a read operation has occurred with an error. When async_read returns with an error you no longer have to take extra steps in your async_write operation to cancel concurrent calls.

Call async_read
Call async_write
async_read callback returns with error (do not call async_read again)
async_write returns with error (do not call async_write again)

So when calling async_write check a flag (iswriting) if the flag is true, then push your buffer into your que. When the callback returns, check your que, pull the next buffer and call async_write again. If iswriting is false, then just call async_write instead of pushing it to the que. If your callback returns and your que is finally empty then set iswriting to false again.

This is all pretty straight forward...

Upvotes: 1

Related Questions