async_write 连续两次出现问题
Problem with async_write two times in a row
当我调用 async_write 2 次时,第二条消息没有发送到服务器。在写入处理程序中,我调用 async_read,当我 运行 我的代码时,程序卡在读取状态。
在连接处理程序中:
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));
在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();
}
在写入处理程序中我调用:
BA::post(io_context, boost::bind(&ssd::read_msg, clientSocketPtr));
然后在 read_msg 我调用 async_read.
输出为文本:
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"}
您一次只能有一个 async_write
未完成。请注意,async_write
是根据 async_write_some
实现的,并且两次写入可以交错。
我做了一些研究,并使用 strand 和制作消息队列解决了我的问题。首先,重要的是将消息推送到队列,然后调用将检查队列是否为空的函数。如果不是,代码将处理该消息并调用 async_write
,紧接着它将从消息队列中弹出该消息。在写入处理程序代码调用 async_read
之后,它会立即检查队列是否再次为空。如果不是,它调用写函数。
一些伪代码:
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()
}
}
当我调用 async_write 2 次时,第二条消息没有发送到服务器。在写入处理程序中,我调用 async_read,当我 运行 我的代码时,程序卡在读取状态。 在连接处理程序中:
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));
在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();
}
在写入处理程序中我调用:
BA::post(io_context, boost::bind(&ssd::read_msg, clientSocketPtr));
然后在 read_msg 我调用 async_read.
输出为文本:
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"}
您一次只能有一个 async_write
未完成。请注意,async_write
是根据 async_write_some
实现的,并且两次写入可以交错。
我做了一些研究,并使用 strand 和制作消息队列解决了我的问题。首先,重要的是将消息推送到队列,然后调用将检查队列是否为空的函数。如果不是,代码将处理该消息并调用 async_write
,紧接着它将从消息队列中弹出该消息。在写入处理程序代码调用 async_read
之后,它会立即检查队列是否再次为空。如果不是,它调用写函数。
一些伪代码:
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()
}
}