如何为Boost.Asio设计自定义IO对象

0xe*_*xee 5 c++ boost boost-asio

我有一个代表要与之通信的嵌入式设备的基类(DeviceBase)。可以通过多种方式访问​​该设备,包括USB和TCP套接字。此外,还有一个可在文件上运行的模拟实现。

到目前为止,我仅使用了同步读/写调用,并且所有实现都是从基类派生的类,这些类重写了读/写功能。这使我可以使用多态指针和容器来提供与设备无关的对应用程序逻辑的访问。

现在我想使用Boost.Asio来启用简单的异步IO。我在http://www.highscore.de/cpp/boost/asio.html上找到了该指南,该指南描述了如何编写自己的扩展名,但是它相当简单,我偶然发现了一些此处未讨论的问题。

  • 当前,我所有的实现都有不同的构造函数(显然,由于寻址/初始化设备连接的方法不同)。本指南中介绍的实现类是由io_service构造的,这意味着用户无法将参数传递给构造函数。

  • 本指南中的示例提供了形式为的模板类,该模板类custom_io_object<implementation>将防止使用多态指针,因为现在对于不同种类的IO对象没有通用的基类。

是否有任何形式的文档或讨论Boost.Asio扩展设计的书籍?我会忽略什么吗?

ken*_*nba 2

听起来基于继承的解决方案可能更适合您。

\n\n

Here\xe2\x80\x99s 是一个使用的示例基类boost::signals2发出接收到的消息信号:

\n\n
class Connection\n{\npublic:\n\n  typedef boost::signals2::signal<void (const std::vector<char>&)>\n     PacketReceived;\n\nprotected:\n  PacketReceived packet_received_;\n  size_t max_rx_packet_size_;\n  std::vector<char> read_buffer_;\n  std::deque<std::vector<char> > tx_queue_;\n\n  void read_handler(boost::system::error_code const& error,\n                    size_t bytes_transferred)\n  {\n    if (boost::asio::error::operation_aborted != error)\n    {\n      if (error)\n        ; // TODO handle the error, it may be a disconnect.\n      else\n      {\n        read_buffer_.resize(bytes_transferred);\n        packet_received_(read_buffer_);\n        enable_reception(max_rx_packet_size_);\n      }\n    }\n  }\n\n  void write_handler(boost::system::error_code const& error,\n                     size_t bytes_transferred)\n  {\n    if (boost::asio::error::operation_aborted != error)\n    {\n      tx_queue_.pop_front();\n      if (error)\n        ; // TODO handle the error, it may be a disconnect.\n      else\n        if (!tx_queue_.empty())\n          transmit();\n    }\n  }\n\n  virtual void receive() = 0;\n\n  virtual void transmit() = 0;\n\n  explicit Connection() :\n    packet_received_(),\n    max_rx_packet_size_(),\n    read_buffer_(),\n    tx_queue_()\n  {}\n\npublic:\n\n  virtual void close() = 0;\n\n  virtual ~Connection()\n  {}\n\n  void connectPacketReceived(const PacketReceived::slot_type& slot)\n  { packet_received_.connect(slot); }\n\n  void enable_reception(size_t max_rx_packet_size)\n  {\n    max_rx_packet_size_ = max_rx_packet_size;\n    receive();\n  }\n\n  const std::vector<char>& read_buffer() const\n  { return read_buffer_; }\n\n#if defined(BOOST_ASIO_HAS_MOVE)\n  void send(std::vector<char>&& packet )\n#else\n  void send(const std::vector<char>& packet )\n#endif\n  {\n    bool queue_empty(tx_queue_.empty());\n    tx_queue_.push_back(packet);\n    if (queue_empty)\n      transmit();\n  }\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

下面是实现 SSL 套接字的类的概要:

\n\n
class SslConnection :\n    public Connection,\n    public boost::enable_shared_from_this<SslConnection>\n{\n  boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket_;\n\n  virtual void receive()\n  {\n    ssl_socket_.async_read_some(boost::asio::buffer(read_buffer_),\n         boost::bind(&SslConnection::read_handler, shared_from_this(),\n                     boost::asio::placeholders::error,\n                     boost::asio::placeholders::bytes_transferred));\n  }\n\n  virtual void transmit()\n  {\n    boost::asio::async_write(ssl_socket_,\n                             boost::asio::buffer(tx_queue_.front()),\n         boost::bind(&SslConnection::write_handler, shared_from_this(),\n                     boost::asio::placeholders::error,\n                     boost::asio::placeholders::bytes_transferred));\n  }\n\n  SslConnection(boost::asio::io_service&   io_service,\n                boost::asio::ssl::context& ssl_context) :\n    Connection(),\n    ssl_socket_(io_service, ssl_context)\n  {}\n\npublic:\n\n  static boost::shared_ptr<SslConnection> create\n                     (boost::asio::io_service&   io_service,\n                      boost::asio::ssl::context& ssl_context)\n  {\n    return boost::shared_ptr<SslConnection>\n        (new SslConnection(io_service, ssl_context));\n  }\n\n  virtual void close()\n  {\n    boost::system::error_code ignoredEc;\n    ssl_socket_.lowest_layer().close(ignoredEc);\n  }\n};\n
Run Code Online (Sandbox Code Playgroud)\n