Dronov Dmitrii
Dronov Dmitrii

Reputation: 23

Problem with async_write two times in a row

When I call async_write 2 times the second message isn't sent to the server. In write handler I call async_read and when I run my code, the program is stuck on read. In connection handler:

clientSocketPtr->lowest_layer().set_option(BA::ip::tcp::no_delay(true));
clientSocketPtr->set_verify_mode(BA::ssl::verify_peer);
clientSocketPtr->set_verify_callback(BA::ssl::host_name_verification(ADDRESS));
clientSocketPtr->handshake(ssl_socket::client);
//first call with first message(76 bytes)
BA::post(io_context, boost::bind(&ssd::write_msg, message, clientSocketPtr)); 
//some code here
//second call with another message(160 bytes)
BA::post(io_context, boost::bind(&ssd::write_msg, message, clientSocketPtr)); 

In write_msg:

void ssd::write_msg(ssd::Message &msg, ssd::ssl_socket *clientSocketPtr) {
//some code here
BA::async_write(*clientSocketPtr, BA::buffer(buf, bufSize), BA::transfer_exactly(bufSize), boost::bind(&ssd::write_handler,
BA::placeholders::error, BA::placeholders::bytes_transferred, clientSocketPtr)); 
io_context.run();
}

In write handler I call:

BA::post(io_context, boost::bind(&ssd::read_msg, clientSocketPtr));

And in read_msg I call async_read.

Output as text:

I20200818 11:17:38.633821  7417 message.hpp:53] 
Message type: 1
Message length: 70
Message: {"cli_type":"tarball","cli_version":"v2020.07.18","cmd":"cli_version"}
I20200818 11:17:38.637073  7417 sslconnection.cpp:77] Bytes sent: 76
I20200818 11:17:38.637115  7417 sslconnection.cpp:77] Bytes sent: 160
I20200818 11:17:38.640669  7417 sslconnection.cpp:109] Bytes recieved: 6
I20200818 11:17:38.640744  7417 sslconnection.cpp:122] Bytes recieved: 47
I20200818 11:17:38.640764  7417 sslconnection.cpp:128] 
Message length: 47
Message: {"cmd":"be_version","be_version":"v2020.07.15"}

Upvotes: 2

Views: 407

Answers (2)

Dronov Dmitrii
Dronov Dmitrii

Reputation: 23

I've done some research and solved my problem using strand and making a message queue. First of all, it is important to push messages to the queue and then call the function which will check if queue isn't empty. If it isn't, the code will process the message and call async_write and right after this it will pop this message from message queue. In write handler code calls async_read and right after this it checks if the queue isn't empty again. If it isn't, it calls write function. Some pseudo code:

msg_queue.push("First");
msg_queue.push("Second");
writeMsg();

writeMsg() {
    if (!msg_queue.empty()) {
    //proccess the message
    async_write(message);
    msg_queue.pop();
    } 
}

write_handler() {
    if(!error) {
        readMsg();
        if (!msg_queue.empty())
            write_msg()
    }

}

Upvotes: 0

janm
janm

Reputation: 18359

You can only have one async_write outstanding at a time. Note that async_write is implemented in terms of async_write_some, and the two writes could be interleaved.

Upvotes: 5

Related Questions