How to maintain asynchronous asynchronous view asive

I am creating a tcp client that needs to send requests and read responses, but also needs to be able to detect incoming data from a tcp server that is not a response to a request - the server can initiate a tx / rx sequence.

What is the best way to keep the async read active all the time. I tried the following:

In my handle_connect method, I trigger async read as well as async write. An asynchronous read looks like this:

    size_t bytes_transferred = BUFFER_SIZE;
    boost :: asio :: async_read (m_socket,
        boost :: asio :: buffer (rcvbuf, bytes_transferred),
        boost :: bind (& CClientSock :: handle_read, 
        boost :: asio :: placeholders :: error,
        boost :: asio :: placeholders :: bytes_transferred));

Asynchronous writing fills the buffer and then starts writing:

    boost :: asio :: async_write (m_socket,
        boost :: asio :: buffer (sndbuf, request_length),
        boost :: bind (& CClientSock :: handle_write, 
        boost :: asio :: placeholders :: error,
        boost :: asio :: placeholders :: bytes_transferred));

In the async handler, write - it does nothing since the async read has already started.

This does not work. Data that needs to be read from the server's response to a client write never triggers an asynchronous read handler. I'm not really sure if the records are ever played ...

Is it possible to do this since reads and writes are not queued normally? Should I start reading and then cancel if I need to start writing?


source to share

2 answers

In the absence of a clear SSCCE / sample, I have highlighted a few ideas:

  • to accept "unregistered" incoming data / requests, you typically use a listener to accept new incoming connections, rather than waiting indefinitely on the same connection.
  • if you need to organize different asynchronous tasks on the same resource, use Boost Asio strand

    : Why do you need a line for each connection when using boost :: asio? ">
  • to continue reading asynchronously Actor, simply post the read operation from the completion handler for the previous read operation:

     void handle_read(boost::system::error_code ec, size_t bytes_received) {
         if (!ec)
             /* do your usual handling on the incoming data */
                boost::asio::buffer(rcvbuf, bytes_transferred),



Well, I have an answer to my original question, but I figured out that I can use threads so I don't have a complete understanding.

My initial problem was with restructuring the code and not realizing that my previous code only worked in the circumstances that I was testing. Now it works for me using the following sequence:

  • Issue async_connect message.
  • In the connect_handler issue async_read_some - it was originally async_read, which was never completed due to the number of bytes available. This caused the stack overflow question.
  • The connect_handler also emits async_write.
  • Do nothing in write_handler because the read is already queued.
  • Writing triggers a response from the server and read_handler is called correctly.
  • read_handler processes the data and prioritizes another async_read_some.

This sequence seems to repeat itself indefinitely without error.

As far as threads are concerned - the code is multithreaded, so there are multiple threads and each thread can handle multiple socket connections. There are no socket calls in threads, that is, the socket never acts in code other than the one in which the socket was created. However, there is only one io_service object for the project, which seems to be the recommended way to use the io_service object in a multithreaded application.

Am I fixing that threads are not needed here?



All Articles