【问题标题】:boost::asio::async_write mixing data from two messages (bug) [duplicate]boost::asio::async_write 混合来自两条消息的数据(错误)[重复]
【发布时间】:2016-11-02 09:06:29
【问题描述】:

我将 boost::asio 用于异步客户端和服务器。 在工作过程中,客户端向服务器发送不同类型的数据:小型服务消息(5-50 B)和带有原始图像数据的最大消息(40-200 KB)。 当我按顺序调用 Client::send 时(在一个线程中,依次):

  1. 发送“小服务消息”;
  2. 发送“大图信息”;

我在服务器湖上得到混合数据(错误):

|大消息开始||小消息||大消息结束|

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

输出显示小消息作为第二条发送到 async_write,但在大消息之前作为第一条执行(完成)。

***** 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 *****

这怎么可能以及如何同步?谢谢!

更新

我不需要同步任务队列。我需要同步两个不同缓冲区大小的 async_write 操作。

【问题讨论】:

  • 我看到你更新了你的问题;我确认您应该使用队列来对“大消息”和“小消息”进行排序,或者从第一个回调中调用第二个写入。

标签: c++ asynchronous client-server boost-asio


【解决方案1】:

这不是错误。文档 (http://www.boost.org/doc/libs/1_62_0/doc/html/boost_asio/reference/async_write/overload1.html) 明确指出,在有另一个正在进行的操作之前,不应在同一个套接字上执行其他写操作。 这是因为async_write 在多次调用async_write_some 时被翻译。 如果您在同一个线程上,我的建议是使用写入队列,在其中添加要发送的数据,然后在写入回调中提取它以执行另一个操作。

【讨论】:

  • Strands 是在 Asio 中用于此用途的逻辑线程(参见 stackoverflow.com/a/12801042/85371
  • @sehe 实际上不确定股线。从文档来看,这些链似乎意味着没有 handlers 将同时执行。这里的问题在于写操作,而不是处理程序执行。此外,链不授予操作之间的排序。我不知道这对操作是否重要,但既然他说他在单线程环境中,我认为他们不会有帮助。
  • 单线程确实意味着单个逻辑链。我应该说我的意思是在同一个(逻辑/隐式)链上的前一个完成处理程序中发布下一个操作。我同意使用队列来适应 OP 显示的界面可能会更容易
猜你喜欢
  • 1970-01-01
  • 2012-08-12
  • 1970-01-01
  • 1970-01-01
  • 2011-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-01
相关资源
最近更新 更多