提振.Asio async_write和strand



我使用链来避免使用Boost.Asio在TCP服务器上并发写。但它似乎只会阻止处理程序的并发执行。

事实上,如果我做两个连续的async_write,一个有一个非常大的数据包,另一个有一个非常小的数据包,wireshark会显示交错。由于async_write是由async_write_some的多个调用组成的,因此我的第二次写入的处理程序似乎可以在第一次调用的两个处理程序之间执行。这对我很不好。

Wireshark输出: [Packet 1.1] [Packet 1.2] [Packet 2[数据包1.3]…(包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
}
}
)
);
}

和主:

int main()
{
tcp_server.write(big_packet); // Packet 1 = 10 MBytes !
tcp_server.write(small_packet); // Packet 2 = 64 kbytes
}

在我的情况下链不合适吗?

p。S:我在这里看到了一个相近的话题,但在我看来,它没有涵盖相同的用例。

您必须确保您的异步操作是从链启动的。您的代码目前没有显示这种情况。希望这能有所帮助,否则,请发布MCVE

void tcp_server::write(command_type cmd)
{
post(m_write_strand, [this, cmd] { this->do_write(cmd); });
}

从问题码组成MCVE:

Live On Coliru

#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();
}

最新更新