1

boost::asio クライアント/サーバーの関係に基づいて、サーバー スレッドが「接続待ち」状態にある場合にのみ、サーバー プログラムからクライアント プログラムを起動する必要があります。

私の質問は、その状態の知識を持つ方法ですか?

サンプルとしてasio example/serialization linkを使用し、server.cpp のメイン関数をそのコードに置き換えます。

#include <conio.h>
#include <concrt.h> // wait function
#include <future>
#include <thread>

void server_thread( std::promise<bool>& run )
{ 
    boost::asio::io_service io_service;
    s11n_example::server server(io_service, 123);
    // too early to run.set_value( true );
    io_service.run();
    // too late to run.set_value( true );
}

int main(int argc, char* argv[])
{
    std::promise<bool> run;
    std::thread thrd( server_thread, boost::ref( run ) );
    thrd.detach(); 

    bool launched = run.get_future().get();
    // server is waiting for connection
    // launch the client
    if( launched )
    {
        int rc = system( "start client.exe localhost 123" );
        if( rc )
            std::cerr << "system failed returning " << rc << std::endl ;
    }
    else
        std::cerr << "server_thread failure" << std::endl ;

    std::cout << "hit a key to exit"  ;
    while( !_kbhit() )
        Concurrency::wait( 100 );

    return 0;
}

ありがとう、

4

1 に答える 1

4

つまりs11n_example::server、コンストラクターの呼び出しが完了した直後に、着信接続がキューに入れられる状態になります。


状態と操作の区別を定義すると、これを理解しやすくなる場合があります。状態は、OS がオブジェクトに対して実行できることを決定します。アプリケーションは、アクションを実行する操作を開始し、状態に依存する場合があります。たとえば、ソケットが開いている場合、OS はデータをキューに入れます。読み取り操作は、キューに入れられたデータを取得します。同じことがアクセプターにも当てはまります。アクセプターがリッスン状態の場合、OS は接続をキューに入れます。受け入れ操作は接続を完了し、キューから削除します。

Anacceptor[states]transitions()は次のとおりです。

     .----> [closed] ------.     [closed]:    socket not open
     |                     |     [opened]:    socket open but not listening for
     |                     V                  connections
  close() <------.      open()   [listening]: incoming connections will be
     ^           |         |                  queued until accepted(), causing
     |           |         V                  the connection to be established
[listening]      '---- [opened]
     ^                     |
     |                     |
     '------ listen() <----'

オーバーロードされたさまざまなコンストラクターはacceptor、クローズ、オープン、またはリッスン状態でライフタイムを開始します。の場合s11n_example::server、アクセプターはエンドポイントで構築されるため、このオーバーロードにより、アクセプターは構築後にリッスン状態になります。これは、次のことと同等です。

using boost::asio::ip::tcp;
tcp::endpoint endpoint_(tcp::v4(), 123);
tcp::acceptor acceptor_(io_service); // closed state
acceptor.open(endpoint_.protocol()); // opened state
acceptor.bind(endpoint);
acceptor.listen();                   // listening state

したがって、プロミスはserverが構築された後、 の前に設定できio_service.run()ます。

void server_thread(std::promise<bool>& run)
{ 
    boost::asio::io_service io_service;
    s11n_example::server server(io_service, 123);
    // The server's acceptor is in a listening state, so connection attempts
    // will be queued even without the io_service event loop running.  The
    // server also has an outstanding asynchronous accept operation.
    run.set_value(true);
    // Run the service, this will start an asynchronous loop that accepts 
    // connections.
    io_service.run();
}

注意すべき微妙な点の 1 つは、Boost.Asio のアクセプターが提供しないことです。

  • 接続を受け入れるためのリアクター ベースの操作。したがって、接続が受け入れられる準備が整ったとき (つまり、接続がキューに入れられ、受け入れられるのを待っているとき) を検出することはできません。
  • acceptorがリッスン状態にあるかどうかを検出する高レベルの方法。それにもかかわらず、これはアクセプターのnative_handle. たとえば、 を使用getsockopt()して の値を取得しますSOL_SOCKET/SO_ACCEPTCONN
于 2013-04-08T15:46:38.770 に答える