Boost Asio - 消息内容传输错误

时间:2014-01-27 16:23:04

标签: c++ boost c++11 boost-asio

我正在构建客户端服务器通信。服务器发送Header + Data(使用async_write和单独的IO线程),Client接收固定大小的Header并知道它必须读取多少数据。

问题:有时客户端会收到错误的数据。似乎服务器发送了错误的数据。

void Session::do_write(std::shared_ptr<DataItem> data)
{
    std::lock_guard<std::mutex> lk(doWrite_mutex);

    std::vector<boost::asio::const_buffer> buffers;
    buffers.push_back(boost::asio::buffer(&data->length, sizeof(uint32_t)));
    buffers.push_back(boost::asio::buffer(&data->callbackID, sizeof(uint8_t)));
    buffers.push_back(boost::asio::buffer(&data->isString, sizeof(bool)));
    //Get the data to send into the buffer and make sure the given shared ptr to the data item keeps living until this function is finished.
    buffers.push_back(boost::asio::buffer(data->getData(), data->length));

    boost::asio::async_write(*socket_, buffers, boost::bind(&Session::onSend, this, data, _1,_2));
}

    void Session::onSend(std::shared_ptr<DataItem> data,const boost::system::error_code ec, std::size_t length)
{ //Some logging, nothing special here 
}

数据项是一个多态类,用于处理不同类型的数据(向量,字符串......)。 getData()方法会向实际数据返回const void*(例如,在向量的情况下为myData->data())。数据在DataItem中存储为shared_ptr(以防止其被销毁)。

在大多数情况下,数据传输正确。

我不知道在哪里调试或我做错了什么。

1 个答案:

答案 0 :(得分:3)

对具有未完成async_write()操作的流调用写入操作无法满足async_write()的要求,这可能导致交织的数据。此外,如果多个线程正在为io_service事件循环提供服务,或者从未处理事件循环的线程调用Session::do_write(),那么使用互斥锁将无法满足该线程的线程安全要求。流。这个answer演示了如何使用队列来序列化多个async_write()操作,并使用strand内的异步调用链处理队列,同时满足async_write()和流的要求线程安全。

有关更多详细信息,async_write()函数是一个组合操作,导致对流的async_write_some()函数进行零次或多次调用。因此,如果程序在完成未完成的操作之前不确保流不执行其他写操作,则可以在其他写操作之间混合中间写操作,从而产生交织的数据。此外,这些中间操作在流上调用async_write_some()而未获取doWrite_mutex,可能违反了流的线程安全要求。有关撰写操作和strand用法的详细信息,请参阅此answer