【问题标题】:boost asio stateful socket interfaceboost asio 有状态套接字接口
【发布时间】:2012-06-17 01:05:07
【问题描述】:

我想要一个有状态的通信,但不像 boost 的回显服务器示例。我的套接字将准备好永远读取,每当它接收到新数据时,它都会调用一个虚拟方法dataAvailable(string),但它可以随时调用async_write

void connected(const boost::system::error_code &ec) {
  _socket.async_read_some(boost::asio::buffer(_buffer, max_length),
      boost::bind(&Session::handler_read, this, boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred));
  //boost::asio::async_read(_socket, boost::asio::buffer(_buffer, max_length),
  //    boost::bind(&Session::handler_read, this, boost::asio::placeholders::error,
  //    boost::asio::placeholders::bytes_transferred));
  std::cout << ">> Session::connected()" << std::endl;
}

void handler_read(const boost::system::error_code &ec, size_t bytes_transferred) {
  if(ec) {
    std::cout << ec.message() << std::endl;
  } else {
    //std::copy(_buffer, _buffer+bytes_transferred, data.begin());
    std::string data(_buffer, _buffer+bytes_transferred);
    std::cout << ">> Session[ " << id() << "]" << "::handler_read(): " <<
            bytes_transferred << " " <<  data << std::endl;
    boost::asio::async_write(_socket, boost::asio::buffer(_buffer, max_length),
            boost::bind(&Session::handler_write, this,
            boost::asio::placeholders::error));
    _socket.async_read_some(boost::asio::buffer(_buffer, max_length),
            boost::bind(&Session::handler_read, this, boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    //boost::asio::async_read(_socket, boost::asio::buffer(_buffer, max_length),
        //    boost::bind(&Session::handler_read, this,
        //    boost::asio::placeholders::error,
        //    boost::asio::placeholders::bytes_transferred));
      //call dataAvailable(_buffer);
  }
}

void handler_write(const boost::system::error_code &ec) {
  if(ec) {
    std::cout << ec.message() << std::endl;
  } else {
    _socket.async_read_some(boost::asio::buffer(_buffer, max_length),
            boost::bind(&Session::handler_read, this, boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    //boost::asio::async_read(_socket, boost::asio::buffer(_buffer, max_length),
        //    boost::bind(&Session::handler_read, this,
        //    boost::asio::placeholders::error,
        //    boost::asio::placeholders::bytes_transferred));
  }
}
  1. 这个实施好吗?因为多个线程可能会进行读写操作。其中写入操作是更新矩阵中的某些单元格
  2. 为什么当我使用async_read 而不是async_read_some 时它不起作用(不回显接收到的字符串)
  3. 在我的监听服务器中,我无法调用listen 方法。但它仍然有效。那么为什么会有一个listen方法呢?什么时候使用?
  4. 我想在客户端套接字从客户端退出时得到通知。例如客户端已关闭连接。我该怎么做 ?我出来的方法是阅读read_handler 中的End Of File 但这是唯一的方法吗?
  5. 我有一个会话类,每个会话都有一个套接字。我将Session* 集合存储在会话管理器中。现在,当我关闭一个套接字并 delete 它时,该会话变为空。它可能发生在vector 的中间。那么如何安全地删除 null 会话?

【问题讨论】:

  • 您能否使用self contained reproducer 编辑您的问题,以便我们查看它是如何不起作用的?您发布的代码 sn-p 没有任何明显错误。

标签: c++ boost boost-asio


【解决方案1】:

您的代码存在一个严重问题。想象一下,您拥有非对称网络链接,并且接收比发送快得多。

  1. 接收消息
  2. 执行 async_write(但这需要时间)
  3. 安排下一次阅读
  4. 接收下一条消息
  5. 执行第二个 async_write(第一个尚未完成,链接的另一端会出现垃圾)
  6. 安排下一次阅读
  7. 第一个 async_write 完成并安排另一个 async_read_some

综上所述,你请求asio一次对同一个socket进行多次读写。

为什么当我使用 async_read 而不是 async_read_some 时它不起作用(不回显接收到的字符串)

您发送的数据是否足够 (max_length)?也许您想使用boost::asio::transfer_at_least(min_length)

在我的监听服务器中,我无处调用监听方法。但它仍然有效。那么为什么会有一个listen方法呢?什么时候使用?

你可能在某处创建了接受器对象。

我想在客户端套接字从客户端退出时得到通知。例如客户端已关闭连接。我该怎么做 ?我的方法是通过在 read_handler 中读取文件结尾但这是唯一的方法吗?

您可以创建包装器,它将采用EOF 并进行一些清理。然后你用包装器包装所有自定义处理程序,并将包装器作为处理程序传递给 boost::asio。这样,您只有一个地方可以处理 EOF 错误,如果您愿意的话。

我有一个 Session 类,每个会话都有一个套接字。我将 Session* 集合存储在 Session Manager 中。现在当我关闭一个套接字并删除它时,该会话变为空。它可能发生在向量的中间。那么如何安全地删除那个空会话呢?

在处理程序等中使用boost::shared_ptr,在会话管理器的向量中使用boost::shared_ptrboost::weak_ptr

【讨论】:

    猜你喜欢
    • 2015-02-19
    • 2023-03-19
    • 1970-01-01
    • 2011-10-15
    • 2011-12-05
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    相关资源
    最近更新 更多