2012-02-25 115 views
2

开发一个网络应用程序,我有一个Connection类来管理网络上的发送和接收消息。我正在使用boost :: asio。超负荷提升:: asio :: basic_stream_socket

我现在想让Connection类通过TCP和本地UNIX流套接字处理连接。然而,boost的模板设计让我感到困惑。 AFAICT,local :: stream_protocol :: socket和ip :: tcp :: socket之间没有共享的基类。

我该如何去创建一个封装网络语义的连接,以便其他代码不必处理使用什么协议的细节?

I.E.我想执行如下:

class Connection() { 
    Connection(ip::tcp::endpoint& ep); 
    Connection(local::stream_protocol::endpoint& ep); 

    void send(Buffer& buf); 
} 

我该如何实现这一目标?

回答

1

经过一番琢磨之后,我目前的解决方案是让Connection虚拟的发送和recv功能,以及创建一个模板的子类Connection,大致为:

template <typename Protocol> 
class ConnectionImpl : public Connection { 
    typedef typename Protocol::socket Socket; 
    typedef typename Protocol::endpoint EndPoint; 

    Socket _socket; 
public: 
    ConnectionImpl(boost::asio::io_service& ioSvc, const EndPoint& addr) 
     : Connection(ioSvc), _socket(ioSvc) { 
     _socket.connect(addr); 
    } 

    void trySend() { 
     // Initiate async send on _socket here 
    } 

    void tryRead() { 
     // Initiate async recv on _socket here 
    } 
} 

有没有一种方法,以避免需要子类和使用虚函数?

1

AFAICT, local :: stream_protocol :: socket和ip :: tcp :: socket之间没有共享基类。

有明确的目的上的所有插座对象没有基类中,documentation非常好地描述

不安全的和错误的BSD套接字API的易发环节未列入的理由。例如,对于 示例,使用int表示所有套接字缺少类型安全性。 Boost.Asio中的套接字表示对于每个 协议使用不同的类型,例如,对于TCP人会使用IP :: TCP ::插座,以及UDP一个 使用IP :: UDP ::插座

+1

谢谢你的链接文档。我错过了。 也就是说,增强不支持兼容套接字的共享接口有点限制。 I.E.一个流类型的UNIX套接字与TCP套接字具有非常兼容的语义,因此与可能的一个或两个虚拟函数共享一个基类将会很有用。 – Rawler 2012-03-02 18:06:28

1

使用boost :: ASIO:通用:: stream_protocol ::插座代替。当你调用async_connect()/ connect()时,它将从远程端点提取系列和协议,然后将它们传递给socket()系统调用以创建正确的套接字。

boost::asio::generic::stream_protocol::socket socket_{io_service}; 

if (use_unix_socket) { 
    boost::asio::local::stream_protocol::endpoint unix_endpoint{"/tmp/socketpath.sock"}; 
    socket_.async_connect(unix_endpoint, [](boost::system::error_code ec){ 

    }}; 
} 
else { 
    boost::asio::ip::tcp::endpoint tcp_endpoint{...}; 
    socket_.async_connect(tcp_endpoint, [](boost::system::error_code ec){ 

    }}; 
} 

而且有从升压代码:: ASIO :: basic_socket:

template <typename ConnectHandler> 
    BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, 
     void (boost::system::error_code)) 
    async_connect(const endpoint_type& peer_endpoint, 
     BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) 
    { 
    // If you get an error on the following line it means that your handler does 
    // not meet the documented type requirements for a ConnectHandler. 
    BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; 

    if (!is_open()) 
    { 
     boost::system::error_code ec; 
     const protocol_type protocol = peer_endpoint.protocol(); 
     if (this->get_service().open(this->get_implementation(), protocol, ec)) 
     { 
     detail::async_result_init< 
      ConnectHandler, void (boost::system::error_code)> init(
      BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler)); 

     this->get_io_service().post(
      boost::asio::detail::bind_handler(
       BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(
       ConnectHandler, void (boost::system::error_code)))(
        init.handler), ec)); 

     return init.result.get(); 
     } 
    } 

    return this->get_service().async_connect(this->get_implementation(), 
     peer_endpoint, BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler)); 
    }