0

I use boost::asio for asynchronous client and server. In working process a client send to server data of different type: small service messages (5-50 B) and largest messages (40-200 KB) with raw image data. When I call Client::send in order (in one thread, successively):

  1. send "small service message";
  2. send "large image message";

I get mixed data (wrong) on the server lake as:

|begin of large message||small message||end of large message|

void Client::send(MessageType type, const void* data, int size, bool read_header_after) {
    assert(cstatus.is_connected());

    header.type = type;
    size_t buf_size = sizeof(ProtocolHeader) + size;
    Bytes *p = new Bytes();
    p->resize(buf_size);
    std::memcpy(&p->front(), &header, sizeof(ProtocolHeader));
    if (size) {
        std::memcpy(&p->at(sizeof(ProtocolHeader)), data, size);
    }


    std::cout << "***** SEND start: " << p->size() << " bytes *****" << std::endl;


    ba::async_write(*socket, ba::buffer(&p->front(), buf_size),
                    ba::transfer_exactly(buf_size),
                    [this, p, read_header_after](const boost::system::error_code& ec, std::size_t length) {

        std::cout << "***** SEND complete: "
                  << p->size() << " bytes; ec="
                  << ec.value() << " (" << ec.message() << ") bufsize="
                  << p->size()
                  << " *****"
                  << std::endl;

        size_t buf_size = p->size();
        delete p; // remove sent data

        if (ec) {
            cstatus.set_last_network_error("Client::send " + ec.message());
            connection_failed("send - ec");
        } else if (length < buf_size) {
            connection_failed("send - len");
        } else {
            if (read_header_after) {
                read_header();
            }
            start_check_timer(NORMAL_INTERVAL_DATA_SEND_MILLISEC);
        }
    });
}

Output show that small message send to async_write as second but executed (finished) as the first before large message.

***** SEND start: 53147 bytes *****
***** SEND start: 5 bytes *****
***** SEND complete: 5 bytes; ec=0 (Success) bufsize=5 *****
***** SEND complete: 53147 bytes; ec=0 (Success) bufsize=53147 *****

How it possible and how sync this? Thanks!

Update

I don't need queue of sync tasks. I need sync two async_write operations with different buffers sizes.

Stan Zeez
  • 1,138
  • 2
  • 16
  • 38
  • I see you have updated your question; i confirm that you should either use a queue to sequentialize the "big message" and the "small message" or call the second write from the callback of the first one. – alessandrolenzi Nov 24 '16 at 10:00

1 Answers1

4

It is not a bug. The documentation (http://www.boost.org/doc/libs/1_62_0/doc/html/boost_asio/reference/async_write/overload1.html) explicitly sais that no other write operations should be executed on the same socket until there's another one in progress. This is because an async_write is translated in several calls to async_write_some. If you are on the same thread, my suggestion is to use a write queue in which you add the data to be send, to then extract it on the write callback to perform another operation.

  • 1
    Strands are the logical threads intended for this use in Asio (see http://stackoverflow.com/a/12801042/85371) – sehe Nov 02 '16 at 09:26
  • @sehe not actually sure about strands. From the documentation it looks like the strands are meant to grant that no _handlers_ will execute concurrently. The issue here is in the write operation, rather than in handler execution. Moreover, strands do not grant ordering between the operation. I don't know if this is important for the op, but since he stated that he is on a single thread environment i don't think they would help. – alessandrolenzi Nov 02 '16 at 09:34
  • Single threaded does indeed imply a single logical strand. I should have said I meant to post the next operation in the completion handler of the previous on the same (logica/implicit) strand. I agree to fit the interface shown by OP might be easier with a queue – sehe Nov 02 '16 at 09:54