如何解决boost :: async_write在写入一段时间后失败
| 我有一个非常特殊的问题。我已经编写了一个服务器,该服务器将从第三方接收的数据写入连接的客户端。服务器向客户端写入数据可能会持续一段时间,但是一段时间后,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持有任何类型的锁(即使您在此处也具有异步锁),最好的情况是性能下降,最坏的情况是导致负载下怪异的死锁。例如,如果异步写入完成内联并且您在同一线程/调用栈中的“ 2”上被调用,该怎么办?
我会尝试重构它,以便在写调用期间释放锁定。
无论解决方案是什么,都可以使用更一般的建议:
不要跨I / O锁定
添加一些诊断输出-什么
线程调用每个处理程序,并在
什么顺序?
碰到
静态。应该可以
诊断死锁
过程状态。
,使用链来序列化对特定连接对象的访问。特别是,请检出strand :: wrap()。要查看使用链的其他示例,请查看一些不同的计时器示例(尽管该代码适用于任何async_*()
调用)。
,首先,我不同意表示在异步操作中持有锁是一个问题的评论。
跨过锁:
任何调用回调的函数都是不好的。
任何阻塞操作都是不好的。
async_write
明确保证既不阻塞也不调用处理程序,因此持有锁对我来说似乎很好。
但是,我可以在您的代码中看到一个错误,该错误违反了async_write
的另一个要求。在完成处理程序被调用之前,您不能调用async_write
。那就是你所违反的。
每当调用其中一个处理程序时,m_writeCompleteFlag
就会设置为true
。这意味着您可能会在高负载下违反某些其他N-1插座的ѭ4规则。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。