0

While sending some data to client (multiple chunks of data); if the client stop reading the data after some packets, the server gets stuck on boost::asio::write() which results in unwanted behavior of the product.

We thought of shifting to async_write() and have a timer over it so that if such condition occurs, we could fallback to original good state, but due to design faults we could not use io_service (due to high concurrency) after async_write which resulted in not getting callbacks to stop the timer.

So, is there any way through which (without using io_serivce) we can unblock the write() API.

Somthing like we could execute write() API on a separate thread and terminate it through some timer. But here the question arises, is there any way through which we can clear out the boost buffers which already has some pending write data ?

Any help would be appreciated.

Thanks.

Anon
  • 144
  • 1
  • 11
  • 1
    If you want to terminate the connection you can probably close the socket on timer in another thread (at least native socket api is usually thread safe), so the call will fail and the error should be processed as any other error. Also several options to set the timeout are discussed [in this question](https://stackoverflow.com/questions/291871/how-to-set-a-timeout-on-blocking-sockets-in-boost-asio). – dewaffled Sep 29 '22 at 09:23
  • @dewaffled Thanks for your response. Do we have any way through which we can avoid closing of the socket and just clear out the pending write data ? – Anon Sep 30 '22 at 05:26
  • Just to add one more info, boost::asio::write() API gets stuck when there is "TCP Window Full" as client is not reading the data. Is there any way to handle this scenario. I've already tried setting the SND and RECV timeout using setsockopt – Anon Sep 30 '22 at 07:19

1 Answers1

0

Eventually went with using boost::asio::async_write() but with io_service::poll() -> poll being non-blocking.

run() was not an option as the system is highly concurrent and read/write had to share the same io_service.

Pseudo code looks something like this:

data_to_write = size of data;

set current_bytes_transffered = 0
set timeout_occurred to false
/*
    current_bytes_transffered -> obtained from async_write() callback
    timeout_occurred -> obtained from a seperate timer
*/
while((data_to_write != current_bytes_transffered) || (!timeout_occurred))
{
    // poll() is used instead of run() as the system 
    // has high concurrency and read and write operations
    // shares same io_service
    io_service.poll();
    
    if(data_to_write == current_bytes_transffered)
    {
        // SUCCESS write logic 
    }
    else if(timeout_occurred)
    {
        // timeout logic
    }
}
Anon
  • 144
  • 1
  • 11