[英]Boost.Asio async_write and strands
I 'm using a strand to avoid concurrent writes on TCP server using Boost.Asio
.我正在使用一个链来避免使用
Boost.Asio
在 TCP 服务器上并发写入。 But it seems it only prevents concurrent execution of handlers.但它似乎只会阻止处理程序的并发执行。
Indeed if I do two successive async_write
, one with a very big packet, and the other with a very small one, wireshark shows interleaves.事实上,如果我连续执行两个
async_write
,一个有一个非常大的数据包,另一个有一个非常小的数据包,wireshark 会显示交错。 As async_write
is composed of multiple calls of async_write_some
, it seems that the handler of my second write is allowed to be executed between two handlers of the first call.作为
async_write
由多个调用async_write_some
,好像是我的第二个写的处理程序被允许第一次呼叫的两个处理程序之间执行。 Which is very bad for me.这对我来说非常糟糕。
Wireshark output : [Packet 1.1] [Packet 1.2] [ Packet 2 ] [Packet 1.3] ... [Packet 1.x] Wireshark 输出:[Packet 1.1] [Packet 1.2] [ Packet 2 ] [Packet 1.3] ... [Packet 1.x]
struct Command
{
// Header
uint64_t ticket_id; // UUID
uint32_t data_size; // size of data
// data
std::vector<unsigned char> m_internal_buffer;
}
typedef std::shared_ptr<Command> command_type;
void tcp_server::write(command_type cmd)
{
boost::asio::async_write(m_socket, boost::asio::buffer(cmd->getData(), cmd->getTotalPacketSize()),
boost::asio::bind_executor(m_write_strand,
[this, cmd](const boost::system::error_code& error, std::size_t bytes_transferred)
{
if (error)
{
// report
}
}
)
);
}
and the main:和主要的:
int main()
{
tcp_server.write(big_packet); // Packet 1 = 10 MBytes !
tcp_server.write(small_packet); // Packet 2 = 64 kbytes
}
Is the strand not appropriate in my case ?在我的情况下,股线不合适吗?
PS: I saw that close topic here but it does not cover the same use case in my opinion. PS:我在这里看到了那个接近的话题,但在我看来它没有涵盖相同的用例。
You have to make sure your async operation is initiated from the strand.您必须确保您的异步操作是从链启动的。 Your code currently doesn't show this to be the case.
您的代码目前并未显示这种情况。 Hopefully this helps, otherwise, post a MCVE
希望这会有所帮助,否则,发布MCVE
So eg所以例如
void tcp_server::write(command_type cmd)
{
post(m_write_strand, [this, cmd] { this->do_write(cmd); });
}
Making up a MCVE from your question code:从你的问题代码组成一个 MCVE:
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
using Executor = boost::asio::thread_pool::executor_type;
struct command {
char const* getData() const { return ""; }
size_t getTotalPacketSize() const { return 1; }
};
using command_type = command*;
struct tcp_server {
tcp_server(Executor ex) : m_socket(ex), m_write_strand(ex)
{
// more?
}
void write(command_type cmd);
void do_write(command_type cmd);
tcp::socket m_socket;
boost::asio::strand<Executor> m_write_strand;
};
void tcp_server::write(command_type cmd)
{
post(m_write_strand, [this, cmd] { this->do_write(cmd); });
}
void tcp_server::do_write(command_type cmd)
{
boost::asio::async_write(
m_socket,
boost::asio::buffer(cmd->getData(), cmd->getTotalPacketSize()),
bind_executor(m_write_strand,
[/*this, cmd*/](boost::system::error_code error,
size_t bytes_transferred) {
if (error) {
// report
}
}));
}
int main() {
boost::asio::thread_pool ioc;
tcp_server tcp_server(ioc.get_executor());
command_type big_packet{}, small_packet{};
tcp_server.write(big_packet); // Packet 1 = 10 MBytes !
tcp_server.write(small_packet); // Packet 2 = 64 kbytes
ioc.join();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.