Boost asio asynchronous read and then write - c++

In my socket communication I have a server where at each connection I want to read data first and after I finished reading, I want to write a response. However I want to do it asynchronously, so I can process many incoming connections. The problem with async_read and async_write is, that obviously they are asynchronous and when I start to read, the write operation immediately starts too.
So basically my question is:
How to start reading from a socket, then interrupt reading (when I decided by the communication protocol that all data has been sent) and then start writing and finally close the socket?

Concerning the second part of your question, look for example at this link.
The async_read function has the parameters CompletionCondition completion_condition and ReadHandler handler. These are callbacks. The completion condition should return 0 if you decide that you've read everything you need. Once you are done reading, the handler callback is called. You can call async_write from the handler.

Related

Boost asio async handler in tcp

Maybe this is a very simple question but I did not find an answer to that. I use boost asios tcp class for handling a simple byte protocol. I do async_read_some and the handler does some work. After the handler has been completed I start another async_read_some. Let's assume this handler does a lot of computing. Is there any posibility that incoming data between the handler work and the next call to async_read_some get lost?
No, your OS would continue receiving data until its receive buffers/TCP receive window are full. Once the receive buffer is full, TCP's flow control will make sure that the sender doesn't send more data than the receiver can receive and such no data will be lost.
See https://www.brianstorti.com/tcp-flow-control/ for a good explanation/example.
https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Flow_control

Multiple Boost::ASIO async_send_to in one go

I want to increase the throughput of my udp gameserver which uses Boost ASIO.
Right now, everytime i need to send a packet, i am putting it in a queue, then checking if there is a pending async_send_to operation, if yes, do nothing, if not, call async_send_to.
Then i wait for the write handler to be called and then call async_send_to for the next packet in queue, if any.
The documentation says that it is the way to do it "for TCP socket", but there is NOTHING on the whole internet about UDP socket.
Try it, search it on stackoverflow, you will see nobody talks about this, and for the 2 questions you will find, the question is left ignored by users.
Why is it kept a secret?
And for the 1million dollar question, can i safely call async_send_to multiple time in a row WITHOUT waiting for the write handler to be called?
Thanks in advance.
This logic is meaningless for the UDP protocol since it doesn't need to block send operation. A datagram is either delivered or lost. UDP don't have to store it in the output buffer and resend indefinitely many times until it get ACK packet.
No, you cannot safely call async_send_to multiple times in a row WITHOUT waiting for the write handler to be called. See Asynchronous IO with Boost.Asio to see precisely why.
However, asio supports scatter gather and so you can call async_send_to with multiple buffers, e.g.:
typedef std::deque<boost::asio::const_buffer> ConstBuffers;
std::string msg_1("Blah");
...
std::string msg_n("Blah");
ConstBuffers buffers;
buffers.push_back(msg_1);
...
buffers.push_back(msg_n);
socket_.async_send_to(buffers, tx_endpoint_, write_handler);
So you could increase your throughput by double buffering your message queue and using gathered writes...

Signal server about user-client error from Boost Asio's async_read_some callback function

I'm trying to asynchronously read data from the HTTP server using boost::asio::ip::tcp::socket's member function async_read_some
template<
typename MutableBufferSequence,
typename ReadHandler>
void-or-deduced async_read_some(
const MutableBufferSequence & buffers,
ReadHandler handler);
and I want to know a way how to signal the server that error happened on client's side of an application so that server stops trying to send the rest of the data to the client.
For example suppose I need 10 recursive async_read_some function calls to receive the whole answer from the server. When 4th async_read_some has called its handler function I fail to parse the received data within this handler function because exception of some kind is thrown. Now I want to inform the server that error happened and I don't want to receive the rest of the message. But how should I do this when I'm inside this handler function?
I could callip::tcp::socket::shutdown with ip::tcp::socket::shutdown_type::shutdown_receive argument but than I can't use the same connection for future communication.
I also cant call ip::tcp::socket's cancel member function that cancels ongoing asynchronous operations because at that point no asynchronous operations is actually being handled on that socket - only the callback function of asynchronous operation is being processed.
How should I handle this situation correctly if I don't want to close this connection?
I think you should close connection. In general, you cannot use this connection for future communication. Especially if you do shutdown on it.
If you try to stay with this connection it can receive trash (because of reading part of a previous answer), send trash (because non-complete previous write) or just stay with broken connection (peer host think connection is closed).
I think any error for async_read_some (except operation_aborted) if fatal to this connection.

how to cancel a `boost::asio::read` operation while it's waiting

I am using boost::asio to transfer data to & fro from client to server. I have a reader thread on client side to read data received on the socket on client side. Please note that I am using boost::asio::read on client side & boost::asio::writeon server side.
Not using async_read or async_write. Everything works great.
However when I close my application, 2 out 10 times the app does not cleanly tear down or close properly. It gets hung while closing down The issue is the following:
My closing function gets called when destructors get called during my app's close down. Following is the code of the Close function:
socket.cancel();
socket.close();
boost::system::error_code ec;
socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
The problem is that the boost::asio::read call does not return when it does not get any data & keeps waiting on it. This should be fine as long as I can cancel it. I am trying to do a socket.cancel on it to cancel all read operations while exiting.
However, it doesn't seems to work. I read in some forums that socket.cancel only cancels async_read operations. Is it so ? Then what is the way to cancel a boost::asio::read` operation when my app needs to exit ?
That's the nature of blocking IO.
Indeed socket.cancel() (or even io_service::stop()) will not work on synchronous operations.
The only way to interrupt this is to use socket-level timeouts (but Asio doesn't expose that) or to use asynchronous signals (e.g. pressing Ctrl-C in a terminal sends the child process a SIGINT).
I've previously created a poor-man's wrapper if you insist on running single operations with a timeout:
boost::asio + std::future - Access violation after closing socket
boost::system::error_code _error_code;
client_socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both, _error_code);
Above code help me close sync read immediately.
And sync read wiil return with error code: boost::asio::error::eof
I wonder why your code socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); did not work.
Maybe you should try again.
The error is due to the call to socket.close() before the call to socket.shutdown(). If you close a socket while there is a pending synchronous read(), you will occasionally get that error. It is really due to an expected data race in the underlying asio socket code.
Try removing the socket.close() call. Assuming your socket is wrapped in some kind of shared_ptr, you can let the socket destructor close the underlying socket.
You will still want to call socket.cancel() and socket.shutdown() explicitly in your use case in order to cancel outstanding operations.

Cancel pending recv?

Hi I'm working on a networking project. I've a socket that is listening incoming data. Now I want to archive this: Socket will receive only 100 packets. And there is 3-4 clients. They are sending random data packets infinitely. I'll receive 100 packets and later I'll process them. After process I'll re-start receiving. But at this time there are some pending send() >> recv() operations. Now I want to cancel/discard pending recv operations. I think we'll recv datas and we'll not process them. Any other suggestions? (sorry for bad question composition)
Shutdown and close the connection. That will cancel everything immediately.
Better yet, rearchitect your application and network protocol so that you can reliably tell how much data to receive.
On Windows you can cancel outstanding receives using CancelIO, but that might result in lost data if the receive just happened to read something.
You can use select() or poll() loops.
you can use signal. recv() will return on receiving a signal so you can send a signal from another task to the task that blocks on recv(). But you need to make sure you don't specify SA_RESTART (see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html)
Read http://en.wikipedia.org/wiki/Asynchronous_I/O for more details
I would go with non-blocking sockets + cancellation socket.
You'll have to read into dedicated incremental buffer (as recv() may not receive all the data expected at once - this would be the case if you can only process full messages) and return to select()/poll() in your loop, where you can safely sit and wait for:
next data
next connection
cancellation event from a cancellation socket, to which your other thread will send a cancellation signal (some trivial send()).
UPD: the trivial event may be the number of the socket in the array or its handle - something to identify which one you'd like to cancel.