8

QTcpServerがスレッドとブロッキングに関する舞台裏でどのように機能するかに興味があります。すぐに戻るメソッドがありますQTcpServerlisten()リッスンが正常に開始されると、サーバーはシグナルを送信しnewConnection()ます。listen()メソッドが戻ったときにサーバーがどのようにリッスンしているのか(メインスレッド上にあるのか)に興味があります。QTcpServerを使用したコンソールアプリケーションの通常の例は、次のようなものです。

//main.cpp
int main(int argc, char* argv[])
{
    QCoreApplication app;
    MyServer server;
    app.exec();
}

//MyServer.cpp
MyServer::MyServer(QObject *parent) : QObject(parent)
{
    this->server = new QTcpServer(this);
    connect(server, SIGNAL(newConnection()), this, SLOT(on_newConnection()));
    if (!server->listen(QHostAddress::Any, 1234))
        //do something in case of error
}
void MyServer::on_newConnection()
{
    QTcpSocket* socket = server->nextPendingConnection();
    //do some communication...
}

ネットワークイベントを受信するために、既存および実行中の(またはおそらく)QTcpServerに依存しています。呼び出されることなく正しく動作しますか?QCoreApplicationQRunLoopQCoreApplication::exec()

4

2 に答える 2

17

QtCoreQtNetworkモジュールのソース コードを掘り下げてきました。

Aperantly は、同期非同期QTcpServerの 2 つのモードで動作します。

呼び出し後の同期モードではlisten()、呼び出し元はwaitForNewConnection()ブロッキング メソッドを呼び出すことができます (スレッドは、誰かがリッスン ポートに接続するまでスリープ状態になります)。この方法QTcpServerは、イベント ループのないスレッドで機能します。

非同期モードでは、新しい接続が受け入れられたときにシグナルを送信しますQTcpServernewConnection()しかし、これを行うには、イベント ループの実行が必要です。の根底にあるのQCoreApplicationQEventLoopandですQAbstractEventDispatcher(抽象クラス、具象型は OS に依存します。たとえばQEventDispatcherUNIX)。このイベント ディスパッチャーは、ソケット (ファイル記述子で表される) の状態を監視できます。方法がありregisterSocketNotifier(QSocketNotifier*)ます。このメソッドは、 が呼び出されるたびに のインスタンスQSocketNotifierを作成するクラスのコンストラクターによって呼び出されます。が呼び出されたときに呼び出される唯一のシステム コールは、もちろん、QTcpServerlisten()QTcpServer::listen()listen()イベントループが実行を開始すると、すべての本当の魔法が起こります。イベント ループ (ディスパッチャを使用) は、登録されたソケットに特定の条件があるかどうかを監視します。select()特定の条件 (読み取るデータがある場合、データを書き込むことができる場合、またはエラーが発生した場合) について (カーネルによって) 監視される 1 つ以上のファイル記述子を受け取るシステム コールを呼び出します。呼び出しは、ソケットの条件が満たされるまでスレッドをブロックするか、一定の時間が経過してソケットの条件が満たされない場合に戻ることができます。Qtが呼び出しているかどうかわかりませんselect()待機時間の有無(無期限にブロックする)は、複雑に決定され、変更可能であると思います。そのため、最終的にソケットの条件が満たされると、イベント ディスパッチャーはQSocketNotifierそのソケットに通知QTcpServerし、ソケットはソケットをリッスンしているユーザーに通知し、ソケットは接続を受け入れ、newConnection()シグナルを送信します。


そのため、自体はイベント ループ/ソケット モニタリング システムを呼び出しませんが、接続の非同期受信に使用する をQTcpServer介して依存しています。QSocketNotifier

同期メソッドが呼び出されると、着信接続があるまでスレッドをブロックするすべてのものと呼び出しをwaitForNewConnection()バイパスするだけです。QSocketNotifieraccept()

于 2012-07-27T16:31:33.930 に答える
0

Qt の「舞台裏」機能のほとんどは、QCoreApplication のメイン イベント ループ (シグナル/スロット、タイマーなど) 内で発生します。
例としては JavaScript があります。イベントをバインドしますが、イベント ループはブラウザーによって処理されます。

于 2012-07-26T12:27:12.353 に答える