boost::async_write在写入一段时间后失败
boost::async_write fails after writing for some time
我遇到了一个非常特殊的问题。我编写了一个服务器,它将从第三方接收的数据写入连接的客户端。服务器向客户端写入操作在一段时间内很好,但过了一段时间,async_write要么失败,要么写操作永远不会返回。对于我的程序,如果async_write永远不会返回,那么就不会进行后续写入,并且我的服务器将对从第三方接收的数据进行排队,直到一切都崩溃。
我在下面包含了我的代码:
void ClientPartitionServer::HandleSignal(const CommonSessionMessage& message, int transferSize) {
boost::lock_guard<boost::mutex> lock(m_mutex);
if(m_clientSockets.size() != 0) {
TransferToQueueBuffer(message.GetData(), transferSize);
}
if(m_writeCompleteFlag) {
// TransferToWriteBuffer();
for(vector<boost::asio::ip::tcp::socket*>::const_iterator i = m_clientSockets.begin(); i != m_clientSockets.end(); ++i) {
WriteToClient(*i);
}
}
}
void ClientPartitionServer::WriteToClient(boost::asio::ip::tcp::socket* clientSocket) {
m_writeCompleteFlag = false;
cout << "Iniating write: " << m_identifier << endl;
boost::asio::async_write(
*clientSocket,
boost::asio::buffer(m_queueBuffer.get(), m_queueBufferSize),
boost::bind(
&ClientPartitionServer::HandleWrite, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
));
}
void ClientPartitionServer::HandleWrite(const boost::system::error_code& ec, size_t bytes_transferred) {
boost::lock_guard<boost::mutex> lock(m_mutex);
if(ec != 0) {
cerr << "Error writing to client: " << ec.message() << " " << m_identifier << endl;
// return;
cout << "HandleWrite Error" << endl;
exit(0);
}
cout << "Write complete: " << m_identifier << endl;
m_writeCompleteFlag = true;
m_queueBuffer.reset();
m_queueBufferSize = 0;
}
如有任何帮助,我们将不胜感激。
谢谢。
如果没有看到所有的代码,很难说,但对我来说,在多个(甚至一个)WriteToClient
调用中持有互斥体是一个危险信号。通常,在I/O之间持有任何类型的锁(甚至是异步的),往好了说对性能不利,往坏了说会导致负载下出现奇怪的死锁。例如,如果异步写入以内联方式完成,并且在同一线程/调用堆栈中的HandleWrite
上被调用,会发生什么?
我会尝试重构它,以便在写调用期间释放锁。
无论解决方案是什么,更普遍的建议是:
- 不要跨I/O锁定
- 添加一些诊断输出-什么线程调用每个处理程序,并且在什么顺序
- 点击后尝试调试静止状态。应该能够从
诊断死锁进程状态
使用链序列化对特定连接对象的访问。特别是,请检查strand::wrap()。要查看使用链的其他示例,请查看一些不同的计时器示例(尽管该代码适用于任何async_*()
调用)。
首先,我不同意那些指出在异步操作中持有锁是个问题的评论。
持有锁定:
-
任何调用回调的函数都是坏的。
-
任何阻塞操作都是错误的。
async_write
显式地保证既不阻塞也不调用处理程序,所以对我来说持有锁看起来不错。
但是,我可以在您的代码中看到一个错误,它违反了async_write
的另一个要求。在调用完完成处理程序之前,不允许调用async_write
。这就是你违反的。
每当调用其中一个处理程序时,m_writeCompleteFlag
就会设置为true
。这意味着您可能会在高负载下违反其他N-1套接字的async_write
规则。
- 在做一段时间内检查字符的无限循环
- ExtTextOut 文本的持续闪烁,在一段时间后,文本将恢复为默认字体
- 对于等待以 std::future wait() 返回的函数的 CPU 使用率或检查标志在循环中休眠一段时间哪个更好?
- ::grpc::ServerReaderWriter 对象在另一个线程中一段时间后无法调用
- 一段时间后 CPU 使用率高
- 有没有办法在一段时间后将流程从流出中分离出来
- 在一段时间内更改标签文本
- 布尔函数在一段时间内不起作用
- 解决PNP在一段时间后返回坏的rvec和tvec
- 相机的旋转方向在一段时间后反转
- boost::asio::d eadline_timer 1ms 滞后一段时间
- SDL_Mixer再次播放时,从随机位置开始一段时间,然后从头开始
- 您可以在一段时间内迭代向量
- 列表STL的时间复杂性在一段时间内进行排序
- 我的开关菜单在一段时间循环中出现问题
- 如何在一段时间内更新 QLabel?
- libcurl:curl_easy_performer在一段时间后失败,返回CURLE_SSL_CACERT_BADFI
- 由于ECHILD错误,C++中的system()函数在一段时间内运行良好,但在返回-1时失败.为什么?
- boost::async_write在写入一段时间后失败
- 一段时间后使线程失败