2011-07-12 17 views
1

OS:Linux 64ビットARCH。ブーストASIO非同期アクセプタがリスニングポートを開かない

BOOST:1.46.1

コンパイラ:打ち鳴らす++/GCC。

boost :: asioの例(Chat Server)でモデル化されたtcpアクセプタのワイヤアップを持つコードフラグメントがあります。しかし、私がフラグメントを実行すると、リッスンしているTCPソケットがnetstat listen(linux)に表示されません。しかし、チャットサーバの例がコンパイルされると表示されます。誰かが私が間違っていることを指摘してもらえますか?

#include <boost/asio.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/bind.hpp> 
#include <list> 
#include <iostream> 


using namespace boost::asio; 
    using namespace boost::asio::ip; 

    class ClientConnection 
    { 
    public: 
    ClientConnection(io_service & io_s) 
     : m_socket(io_s) {} 
    tcp::socket & socket() { return m_socket; } 
    private: 
    tcp::socket m_socket; 
    }; 

    typedef boost::shared_ptr<ClientConnection> client_connection_ptr; 

    class ClientConnectionAcceptor 
    { 
    public: 
    ClientConnectionAcceptor(unsigned short port) 
     : m_io_service(), 
     m_port(port), 
     m_endpoint(tcp::v4(), m_port), 
     m_acceptor(m_io_service, m_endpoint) 
    { 
     std::cout << "acceptor is open : " << m_acceptor.is_open() << std::endl; 
     client_connection_ptr ccp(new ClientConnection(m_io_service)); 

     m_acceptor.async_accept( 
     ccp->socket(), 
     boost::bind(&ClientConnectionAcceptor::handle_accept,this, 
     ccp, placeholders::error)); 
    } 

    void handle_accept(client_connection_ptr ccp, const boost::system::error_code & error) 
    { 
     std::cout << "in handle_accept" << std::endl; 
     if(!error) 
     { 
     // m_rpc_oracle.AddNewClient(ccp); 
     client_connection_ptr new_ccp(new ClientConnection(m_io_service)); 
     m_acceptor.async_accept( 
      new_ccp->socket(), 
      boost::bind(&ClientConnectionAcceptor::handle_accept,this, 
      ccp, placeholders::error)); 

     } 
    } 

    io_service & io_service() { return m_io_service; } 
    private: 
    boost::asio::io_service m_io_service; 
    tcp::endpoint m_endpoint; 
    tcp::acceptor m_acceptor; 
    unsigned short m_port; 
    }; 


int main() 
{ 
    ClientConnectionAcceptor acceptor(5000); 
    acceptor.io_service().run(); 
}  

答えて

2

endpointacceptorを共有ポインタに変更し、それらをコンストラクタの引数として渡すことで作成するのではなく、内部で共有ポインタを作成した場合、これをWindowsマシン上で動作させることができます。コンストラクタ。なぜ私はこれがなぜ機能するのか正確には分かりません。私の唯一の推測は、おそらく、コンストラクタの引数が出現順に渡されるか、作成されるという保証がないため、まだ正しく初期化されていないendpointacceptorを作成しようとする可能性があります。それは本当に私の推測です。これがあなたのために働くかどうか私に教えてください。私は正常にlocalhost経由でポート5000に接続することができます。

これらの変更がなければ、localhostで接続しようとしたクライアントから、接続が積極的に拒否されたことが伝えられました。しかし、この配置は成功し、元のコードからできるだけ逸脱しているようです。それが役に立てば幸い。

#include <boost/asio.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/bind.hpp> 
#include <list> 
#include <iostream> 

using namespace boost::asio; 
using namespace boost::asio::ip; 

class ClientConnection 
{ 
public: 
    ClientConnection(io_service & io_s) 
    : m_socket(io_s) {} 
    tcp::socket & socket() { return m_socket; } 
private: 
    tcp::socket m_socket; 
}; 

typedef boost::shared_ptr<ClientConnection> client_connection_ptr; 

class ClientConnectionAcceptor 
{ 
public: 
    ClientConnectionAcceptor(unsigned short port) 
    : m_io_service(), 
    m_port(port) 
    { 
    // now initializing endpoint and acceptor as shared pointers inside the constructor 
    m_endpoint = boost::shared_ptr<tcp::endpoint>(new tcp::endpoint(tcp::v4(), m_port)); 
    m_acceptor = boost::shared_ptr<tcp::acceptor>(new tcp::acceptor(m_io_service, *m_endpoint)); 

    std::cout << "acceptor is open : " << m_acceptor->is_open() << std::endl; 
    client_connection_ptr ccp(new ClientConnection(m_io_service)); 

    m_acceptor->async_accept( 
     ccp->socket(), 
     boost::bind(&ClientConnectionAcceptor::handle_accept,this, 
     ccp, placeholders::error)); 
    } 

    void handle_accept(client_connection_ptr ccp, const boost::system::error_code & error) 
    { 
    std::cout << "in handle_accept" << std::endl; 
    if(!error) 
    { 
     // m_rpc_oracle.AddNewClient(ccp); 
     client_connection_ptr new_ccp(new ClientConnection(m_io_service)); 
     m_acceptor->async_accept( 
     new_ccp->socket(), 
     boost::bind(&ClientConnectionAcceptor::handle_accept,this, 
     ccp, placeholders::error)); 

    } 
    } 

    io_service & io_service() { return m_io_service; } 
private: 
    boost::asio::io_service m_io_service; 
    boost::shared_ptr<tcp::endpoint> m_endpoint; 
    boost::shared_ptr<tcp::acceptor> m_acceptor; 
    unsigned short m_port; 
}; 


int main() 
{ 
    ClientConnectionAcceptor acceptor(5000); 
    acceptor.io_service().run(); 
}  

EDIT

は、さらにいくつかの調査の後、それは問題が実際にClientConnectionAcceptorクラスの初期化子リストに関連していたことが発見されました。クラス定義では、m_portは、m_endpointとの後にと宣言されました。その結果、初期化子リストが作成されたendpointacceptor前にポート番号を設定するために登場していても、実際には、ポートの値が有効かendpointacceptor後には、既に作成されたまでは初期化されていませんでした。 endpointacceptorの前にメンバーm_portを宣言するようにクラス定義を変更すると、問題が解決されます。

+0

うわー、それは問題を解決しました、ありがとうございます。おそらく、初期化リストの初期化順序と関係があります。私はそれがトップダウンだと思った。 –

+0

http://stackoverflow.com/questions/4037219/order-of-execution-in-constructor-initialization-listユーザー "インシリコ"の応答、私の仮定は、そのイニシャライザのリスト順序は、評価の順序を決定した。しかしそれは順序を決定する宣言の順序です。私はまだそれを試してみる必要があります。 –

+0

それはあなたの質問に答えますか、それとも他に何かありましたか? – aardvarkk

1

io_service & get_io_service() { return m_io_service; } 

io_service & io_service() { return m_io_service; } 

を変え、あなたのコード

async_accept.cc:56: error: declaration of ‘boost::asio::io_service& ClientConnectionAcceptor::io_service()’ 
/opt/local/include/boost/asio/io_service.hpp:186: error: changes meaning of ‘io_service’ from ‘class boost::asio::io_service’ 

をコンパイルするコンパイラの障害を解決するようだとき、私はエラーを得ました。結果のバイナリを実行すると、私のためにlistenソケットがnetstat -l -tに表示されます。

関連する問題