2

我想要一个有状态的通信,但不像 boost 的 echo server 示例。我的套接字将准备好永远读取,每当它接收到新数据时,它都会调用一个虚拟方法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. 我想在客户端套接字从客户端退出时收到通知。例如,客户端已关闭连接。我该怎么做 ?我出来的方式是通过阅读End Of Fileinread_handler但这是唯一的方式吗?
  5. 我有一个 Session 类,每个会话都有一个套接字。我将集合存储Session*在会话管理器中。现在,当我关闭一个套接字并且delete该会话变为空时。它可能发生在vector. 那么如何安全地删除该null会话?
4

1 回答 1

0

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

  1. 接收消息
  2. 做 async_write (但这需要时间)
  3. 安排下一次阅读
  4. 接收下一条消息
  5. 做第二个 async_write (第一个还没有完成,你在链接的另一边得到垃圾)
  6. 安排下一次阅读
  7. 第一个 async_write 完成并安排另一个 async_read_some

总而言之,您请求 asio 一次对同一个套接字进行多次读取和写入。

为什么当我使用 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在会话管理器的向量中使用。

于 2012-06-16T16:29:05.173 回答