提问人:junya 提问时间:6/15/2021 更新时间:6/15/2021 访问量:262
Boost Asio:在 mutl-thread 中使用 streambuf 和 async_write 时很奇怪
Boost Asio: Strange when use streambuf and async_write in mutl-thread
问:
我的程序在发送数据时有一个缓冲区。与其每次都直接调用 async_write 发送小包,不如尽量让 send 方法快速返回,使用 streambuf 作为发送缓冲区,尝试发送大包。
现在遇到的问题是,当多个线程同时调用 send 时,另一端接收到重复数据包或凌乱数据的概率很小。这是我的代码:
void ClientConnection::send(const string* buffer, function<void (bool status)> callback) {
{
unique_lock<mutex> lck(*_ioLockPtr);
ostream os(_sendBufferPtr.get());
os << *buffer;
}
delete buffer;
callback(true);
_sendBuffer();
}
void ClientConnection::_sendBuffer() {
unique_lock<mutex> lck(*_ioLockPtr);
size_t bufferSize = _sendBufferPtr->size();
if (!bufferSize || _sendingBufferCount > 0) {
return;
}
++_sendingBufferCount;
async_write(*_socketPtr, _sendBufferPtr->data(), boost::asio::transfer_exactly(bufferSize), boost::bind(&ClientConnection::_handleWrite,
shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
_sendBufferPtr->consume(bufferSize);
}
void ClientConnection::_handleWrite(const boost::system::error_code& error, size_t bytes_transferred) {
if (!error) {
unique_lock<mutex> lck(*_ioLockPtr);
size_t bufferSize = _sendBufferPtr->size();
if (bufferSize) {
async_write(*_socketPtr, _sendBufferPtr->data(), boost::asio::transfer_exactly(bufferSize), boost::bind(&ClientConnection::_handleWrite,
shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
_sendBufferPtr->consume(bufferSize);
} else {
--_sendingBufferCount;
}
} else {
{
unique_lock<mutex> lck(*_ioLockPtr);
--_sendingBufferCount;
}
_close();
}
}
相关变量定义如下:
shared_ptr<boost::asio::streambuf> _sendBufferPtr;
uint8_t _sendingBufferCount;
请帮我了解如何解决这个问题,谢谢!
答:
2赞
sehe
6/15/2021
#1
现在遇到的问题是,当多个线程同时调用 send 时
根据文档,这是严格禁止的:
此操作是通过对流的 async_write_some 函数的零次或多次调用来实现的,称为组合操作。程序必须确保流在此操作完成之前不执行其他写入操作(例如async_write、流的async_write_some函数或执行写入的任何其他组合操作)。
若要序列化异步操作,可能需要使用链。
评论