6

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

到目前为止,我只使用了同步读/写调用,所有的实现都是简单的从基类派生的类,覆盖了读/写函数。这允许我使用多态指针和容器来提供对设备对应用程序逻辑的独立于实现的访问。

现在我想使用 Boost.Asio 来启用简单的异步 IO。我发现本指南http://www.highscore.de/cpp/boost/asio.html描述了如何编写自己的扩展,但它非常简化,而且我偶然发现了一些在那里没有讨论的问题。

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

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

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

4

1 回答 1

2

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

这是一个示例基类,boost::signals2用于发出接收到的消息的信号:

class Connection
{
public:

  typedef boost::signals2::signal<void (const std::vector<char>&)>
     PacketReceived;

protected:
  PacketReceived packet_received_;
  size_t max_rx_packet_size_;
  std::vector<char> read_buffer_;
  std::deque<std::vector<char> > tx_queue_;

  void read_handler(boost::system::error_code const& error,
                    size_t bytes_transferred)
  {
    if (boost::asio::error::operation_aborted != error)
    {
      if (error)
        ; // TODO handle the error, it may be a disconnect.
      else
      {
        read_buffer_.resize(bytes_transferred);
        packet_received_(read_buffer_);
        enable_reception(max_rx_packet_size_);
      }
    }
  }

  void write_handler(boost::system::error_code const& error,
                     size_t bytes_transferred)
  {
    if (boost::asio::error::operation_aborted != error)
    {
      tx_queue_.pop_front();
      if (error)
        ; // TODO handle the error, it may be a disconnect.
      else
        if (!tx_queue_.empty())
          transmit();
    }
  }

  virtual void receive() = 0;

  virtual void transmit() = 0;

  explicit Connection() :
    packet_received_(),
    max_rx_packet_size_(),
    read_buffer_(),
    tx_queue_()
  {}

public:

  virtual void close() = 0;

  virtual ~Connection()
  {}

  void connectPacketReceived(const PacketReceived::slot_type& slot)
  { packet_received_.connect(slot); }

  void enable_reception(size_t max_rx_packet_size)
  {
    max_rx_packet_size_ = max_rx_packet_size;
    receive();
  }

  const std::vector<char>& read_buffer() const
  { return read_buffer_; }

#if defined(BOOST_ASIO_HAS_MOVE)
  void send(std::vector<char>&& packet )
#else
  void send(const std::vector<char>& packet )
#endif
  {
    bool queue_empty(tx_queue_.empty());
    tx_queue_.push_back(packet);
    if (queue_empty)
      transmit();
  }
};

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

class SslConnection :
    public Connection,
    public boost::enable_shared_from_this<SslConnection>
{
  boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket_;

  virtual void receive()
  {
    ssl_socket_.async_read_some(boost::asio::buffer(read_buffer_),
         boost::bind(&SslConnection::read_handler, shared_from_this(),
                     boost::asio::placeholders::error,
                     boost::asio::placeholders::bytes_transferred));
  }

  virtual void transmit()
  {
    boost::asio::async_write(ssl_socket_,
                             boost::asio::buffer(tx_queue_.front()),
         boost::bind(&SslConnection::write_handler, shared_from_this(),
                     boost::asio::placeholders::error,
                     boost::asio::placeholders::bytes_transferred));
  }

  SslConnection(boost::asio::io_service&   io_service,
                boost::asio::ssl::context& ssl_context) :
    Connection(),
    ssl_socket_(io_service, ssl_context)
  {}

public:

  static boost::shared_ptr<SslConnection> create
                     (boost::asio::io_service&   io_service,
                      boost::asio::ssl::context& ssl_context)
  {
    return boost::shared_ptr<SslConnection>
        (new SslConnection(io_service, ssl_context));
  }

  virtual void close()
  {
    boost::system::error_code ignoredEc;
    ssl_socket_.lowest_layer().close(ignoredEc);
  }
};
于 2013-10-30T18:11:22.497 回答