提升asio有状态套接字接口

时间:2012-06-15 05:43:27

标签: c++ boost boost-asio

我想要有状态的通信但不喜欢boost的echo服务器示例。我的套接字将为永久阅读做好准备,每当收到新数据时,它都会调用虚拟方法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. 时,为什么它不起作用(不回显收到的字符串)
  4. 在我的侦听服务器中,我无处调用listen方法。但仍然有效。那为什么有一个listen方法呢?何时使用?
  5. 我希望在从客户端退出客户端套接字时收到通知。例如客户已关闭连接。我该怎么做 ?我出来的方法是在End Of File中阅读read_handler但这是唯一的方法吗?
  6. 我有一个Session类,每个会话都有一个套接字。我在会话管理器中存储Session*个集合。现在,当我关闭套接字并delete时,该会话变为空。它可能发生在vector的中间。那么如何安全地删除null会话?

1 个答案:

答案 0 :(得分:0)

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

  1. 接收消息
  2. 执行async_write(但需要时间)
  3. 安排下一次阅读
  4. 接收下一条消息
  5. 做第二个async_write(第一个还没有完成,你在链接的另一边得到垃圾)
  6. 安排下一次阅读
  7. 首先,async_write完成并再安排一次async_read_some
  8. 总而言之,您要求asio一次执行多次读取和写入。

      

    当我使用async_read而不是async_read_some

    时,为什么它不起作用(不回显收到的字符串)

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

      

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

    您可能在某处创建了acceptor对象。

      

    我希望在从客户端退出客户端套接字时收到通知。例如客户已关闭连接。我该怎么做 ?我出来的方法是通过读取read_handler中的End of File但这是唯一的方法吗?

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

      

    我有一个Session类,每个会话都有一个套接字。我在会话管理器中存储Session * colection。现在,当我关闭套接字并删除它时,该会话变为空。它可能发生在矢量中间。那么如何安全地删除那个空会话?

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