2012-02-25 20 views
2

ネットワークアプリケーションを開発するには、ネットワーク上でメッセージの送受信を管理するConnectionクラスがあります。私はboost :: asioを使用しています。オーバーロード可能boost :: asio :: basic_stream_socket

ここで、ConnectionクラスがTCPとローカルUNIXストリームソケットの両方で接続を処理できるようにしたいと考えています。しかし、ブーストのテンプレートデザインは私を混乱させる。 AFAICTでは、local :: stream_protocol :: socketとip :: tcp :: socketの間に共有ベースクラスはありません。

どのようなプロトコルが使用されているかの詳細を他のコードで処理する必要がないようにネットワークセマンティクスをカプセル化するConnectionを作成するにはどうすればよいですか?

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のための1つのIPアドレスを使用する:: TCP ::ソケット、およびUDP 1 用:: UDP ::ソケット

+1

は、リンクドキュメントをいただき、ありがとうございます。私はそれを逃した。 これは、互換性のあるソケットの共有インターフェイスをサポートしていないことを少し制限しています。 I.ストリーム型のUNIXソケットは、TCPソケットと非常に互換性のあるセマンティクスを持っているため、おそらく1つまたは2つの仮想関数で基本クラスを共有すると便利です。 – Rawler

1

利用ブースト:: ASIO IPを使用しています:ジェネリック:: 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)); 
    }