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规则。     

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...