问题描述
我建立一个客户端服务器通信。服务器发送头+数据(使用async_write和一个单独的IO线程),客户端收到固定大小的头,并且知道它有多少数据读取。
I am building a client server communication. The server sends Header+Data (using async_write and a seperate IO Thread), Client receives Header of fixed size and knows how much data it has to read.
问题:有时客户端收到错误的数据。这似乎是服务器发送了错误的数据。
The Problem: Sometimes the client receives wrong data. It seems like the server sends the wrong data.
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()
方法返回一个常量无效*
来的实际数据(例如: myData- &GT;数据()
在向量的情况下)。数据存储为的shared_ptr
的DataItem的(以防止它被销毁)。在
The data item is a polymorphic class to handle different kinds of data (vectors, strings,...). The getData()
method returns a const void*
to the actual data (e.g. myData->data()
in case of vector). The data is stored as a shared_ptr
inside the DataItem (to keep it from being destroyed).
在大多数情况下,数据被正确地发送。
In most cases the data is transmitted correctly.
我不知道在哪里调试还是什么我做错了。
I don't know where to debug or what I am doing wrong.
推荐答案
这是一个具有优秀的 async_write()
操作流调用的写操作不符合要求的 async_write()
,这可能会导致数据的交织。此外,如果将多个线程维修 io_service对象
事件循环或会话:: do_write()
是从一个线程调用的不处理事件循环,则使用一个互斥的将不符合流的线程安全要求。这演示使用队列序列化多个 async_write()
操作和处理队列中一个的,履行 async_write双方的要求()
和流的线程安全。
Invoking a write operation on a stream that has an outstanding async_write()
operation fails to meet a requirement of async_write()
, which can result in interwoven data. Additionally, if multiple threads are servicing the io_service
event loop or Session::do_write()
is invoked from a thread that is not processing the event loop, then the use of a mutex will fail to meet the thread safety requirement of the stream. This answer demonstrates using a queue to serialize multiple async_write()
operations, and processing the queue with an asynchronous call chain within a strand
, fulfilling both the requirements of async_write()
and the stream's thread safety.
有关进一步的细节,函数是一个沉稳的操作,造成零或多次调用流的 async_write_some()
功能。因此,如果程序不确保流直到优秀操作完成不执行任何其它的写入操作中,中间的写操作可以被其它的写入操作之间混合,产生交织数据。此外,这些中间业务调用 async_write_some()
流上,而不必获得 doWrite_mutex
,可能违反线程安全要求的流。有关由运营和链
使用的更多信息,可以考虑阅读这篇回答。
For further details, the async_write()
function is a composed operations, resulting in zero or more calls to the stream's async_write_some()
function. Therefore, if the program does not ensure that the stream performs no other write operations until the outstanding operation completes, the intermediate write operations can be mixed between other write operations, resulting in interwoven data. Furthermore, these intermediate operations invoke async_write_some()
on the stream without having acquired doWrite_mutex
, potentially violating the thread safety requirement for the stream. For more information about composed operations and strand
usage, consider reading this answer.
这篇关于升压短耳 - 留言内容发送错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!