2016-08-07 12 views
0

私がまったく同じことを自分自身で実装しようとするまで、すべてのブーストの例が機能します。私は、物事が適切にブロックされるための創造またはio_serviceの所有権がなければならないと考え始めています。io_service.run()がブロックされていません。サーバーが作成されてすぐに終了する

次のように私のサーバー構成は次のとおりです。

class Server { 
    public: 
    Server(unsigned short port) 
    : ioService_(), acceptor_(ioService_), socket_(ioService_) { 
     acceptClient(); // begin async accept 
    } 

    void start(); // runs ioService_.run(); 

    private: 

    void acceptClient(); 

    asio::io_service ioService_; 
    tcp::acceptor acceptor_; 
    tcp::socket socket_; 
    Cluster cluster_; // essentially just a connection manager 
}; 

acceptClient()関数は次のように動作します。

void Server::acceptClient() { 
    acceptor_.async_accept(socket_, [this](const system::error_code& e){ 
    if(!acceptor_.is_open()) return; 
    if(!e) { 
     cluster_.add(std::make_shared<Client>(std::move(socket_), cluster_)); 
    } 

    acceptClient(); 
    }); 
} 

私はあなたが以来、Clientクラスの概要を必要とするかどうかわからないんだけどサーバーはクライアントがなくても実行してブロックする必要があります。次のように

サーバーの作成が行く:

try { 
    Server server(port); 
    server.start(); // this calls the server's member io_service's run(); 
} catch (const std::exception& e) { 
    std::cerr << e.what(); << std::endl; 
} 

問題は、サーバーが瞬時にその呼び出しの後に閉じています。プログラムは起動し、エラーなしで終了します。 io_service.run()が依存するものはありますか?例えば私は忘れてしまった何らかの形の非同期リンクですか?私はboost asioのhttpサーバーの設計からこのデザインを学んだが、私は基本的な目的に合うように設計した。問題は、サーバーのクライアントをクライアントに移動するのではなく、クライアント自体に新しいメンバーboost tcp :: socketを設定して、かなり混乱しているということです。彼らはまた、lddasの代わりにstd :: bindのboostのバージョンを使用する傾向があります。

したがって、ブーストの例は本当に混乱しているので、基本的な削除された非同期サーバーを作成する方法について簡単に説明できます。コードの表記法は例ごとに異なります。誰かがすぐに私のサーバーを閉じる原因になるとすぐに気づいたのかどうか疑問に思っていました。

ありがとうございました。

答えて

1

async_acceptを次のコードでテストしました。Helloをポートに接続するクライアントに送信します。少なくとも、endpointオブジェクト、acceptor.open(endpoint.protocol())acceptor.bind(endpoint)acceptor.listen()の呼び出しがコードから抜けているように見えます。

#include <boost/bind.hpp> 
#include <boost/asio.hpp> 
#include <string> 

using namespace boost::asio; 

void handle_accept(
    io_service * ios, 
    ip::tcp::acceptor * acceptor, 
    ip::tcp::socket * socket, 
    const boost::system::error_code & error) 
{ 
    if (!error) { 
     std::string msg("Hello\n"); 
     socket->send(buffer(msg, msg.length())); 

     ip::tcp::socket * temp = new ip::tcp::socket(*ios); 
     acceptor->async_accept(*temp, 
           boost::bind(handle_accept, 
              ios, acceptor, temp, 
              placeholders::error)); 
    } 
} 

int main(void) 
{ 
    io_service ios; 
    ip::tcp::socket socket(ios); 
    ip::tcp::acceptor acceptor(ios); 
    ip::tcp::endpoint endpoint(ip::tcp::v4(), 1500); 
    acceptor.open(endpoint.protocol()); 
    acceptor.set_option(ip::tcp::acceptor::reuse_address(true)); 
    acceptor.bind(endpoint); 
    acceptor.listen(); 

    acceptor.async_accept(socket, 
          boost::bind(handle_accept, 
             &ios, &acceptor, &socket, 
             placeholders::error)); 
    ios.run(); 

    /* 
    acceptor.accept(socket); 
    std::string msg("Hello\n"); 
    socket.send(buffer(msg, msg.length())); 
    */ 
} 

サーバークラスとのバージョンとasync_acceptの引数としてラムダ:

#include <boost/asio.hpp> 
#include <functional> 
#include <string> 

using namespace boost::asio; 

class Server { 
public: 
    Server(unsigned short port) : ios(), acceptor(ios), socket(ios), 
            endpoint(ip::tcp::v4(), port) { 
     acceptor.open(endpoint.protocol()); 
     acceptor.set_option(ip::tcp::acceptor::reuse_address(true)); 
     acceptor.bind(endpoint); 
     acceptor.listen(); 
     nsocket = &socket; 
    } 

    void run() { 
     std::function<void (const boost::system::error_code &)> f; 
     f = [&f, this] (const boost::system::error_code & error) { 
      if (!error) { 
       std::string msg("Hello\n"); 
       nsocket->send(buffer(msg, msg.length())); 

       nsocket = new ip::tcp::socket(ios); 
       acceptor.async_accept(*nsocket, f); 
      } 
     }; 

     acceptor.async_accept(socket, f); 
     ios.run(); 
    } 

protected: 
    io_service ios; 
    ip::tcp::acceptor acceptor; 
    ip::tcp::socket socket; 
    ip::tcp::endpoint endpoint; 

    ip::tcp::socket * nsocket; 
}; 


int main(void) 
{ 
    Server srv(1500); 
    srv.run(); 
} 
+0

おかげでたくさん、エンドポイントの結合についてのご提案が適切に働いていた(私はにエンドポイントを渡すと仮定受諾者のコンストラクタはこれを保証していたはずです)。私は簡単に私のコードにあなたの例を適応させることができた、もう一度感謝:) – oldjohn1994

関連する問題