1

ほとんどの場合、Qt ネットワーキングでスレッドを使用することはやり過ぎであり、特に適切な方法でreadyRead()シグナルを使用する場合は不必要であることを理解しています。ただし、私の「クライアント」アプリケーションでは、一度に複数のソケット (約 5 つ) が開かれます。すべてのソケットに同時にデータが入ってくる可能性があります。受信データに対して集中的な処理を行うつもりはありません。単純にそれを読み込んで信号を送信し、新しく受信したデータで GUI を更新します。入ってくるすべてのデータをシングル スレッド アプリケーションで処理できると思いますか?

コードを示していないことと、私の説明がかなり曖昧であり、実装後のパフォーマンスに大きく依存する可能性があることは理解していますが、一般的な設計の観点と皆さんの専門知識から、あなたの意見はどうですか?

4

3 に答える 3

4

非常に高帯域幅のストリーム (たとえば、1 秒あたりのキロバイトではなく 1 秒あたりのメガバイト) を受信して​​いない限り、シングルスレッドの設計で十分です。OS のネットワーク スタックは常に「バックグラウンドで」実行され、TCP パケットを受信し、受信したデータを固定サイズのカーネル内メモリ バッファー内に格納することに注意してください。これはプログラムの実行と並行して発生するため、ほとんどの場合、プログラムがシングル スレッドであり、GUI の更新 (または別のソケット) の処理でビジーであっても、コンピューターの TCP パケットの受信が妨げられることはありません。

シングルスレッド設計TCP トラフィックの速度低下を引き起こすケースは、(Qt を介した) プログラムが recv() を十分に迅速に呼び出さなかった場合で、ソケットのカーネルの TCP 受信バッファが完全にデータでいっぱいになった場合です。その時点で、カーネルはそのソケットの着信 TCP パケットをドロップし始めるしかありません。これにより、サーバーはそれらの TCP パケットを再送信する必要があり、少なくともソケットの TCP 受信速度が遅くなります。一時的に。ただし、この問題は、バッファがいっぱいにならないようにすることで回避できます (少なくともめったにありません)。

これを行うための明白な方法は、プログラムがすべての着信データをできるだけ早く読み取るようにすることです。これは、QTCPSocket がデフォルトで行うことです。必要な唯一のことは、GUI の更新に過度の時間がかからないようにすることです。また、Qt のウィジェット更新ルーチンはかなり効率的であるため、非常に精巧な GUI や非効率的なカスタム paintEvent() ルーチンなど。

それが十分でない場合、(必要に応じて) 次にできることは、OS の TCP スタックに、カーネル内の TCP 受信バッファーのサイズを増やすように指示することです。たとえば、次のようにします。

 int fd = myQTCPSocketObject.descriptor();
 int newBufSizeBytes = 128*1024;   // request 128kB kernel recv-buffer for this socket
 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &newBufSizeBytes, sizeof(newBufSizeBytes)) != 0) perror("setsockopt");

これを行うと、(単一の) スレッドが、カーネル内のバッファー スペースの不足のために着信パケットがドロップされ始める前に、反応する時間が長くなります。

これらすべてを試しても必要なネットワーク パフォーマンスが得られない場合は、マルチスレッド化を試すことができます。そのようになるとは思えませんが、そうなったとしても、プログラムの設計にあまり影響を与える必要はありません。QTCPSocket オブジェクトを保持し、ソケットからの読み取りを処理する内部スレッドを実行し、スレッドがソケットからデータを読み取るたびに bytesReceived(QByteArray) シグナルを発行するラッパー クラス (SocketThread などと呼ばれる) を作成するだけです。コードの残りの部分はほぼ同じままです。QTCPSocket の代わりに SocketThread オブジェクトを保持するように変更し、SocketThread の bytesReceived(QByteArray) シグナルを対応するスロットに接続し (もちろん、スレッドセーフのために QueuedConnection を介して)、readReady() に直接応答する代わりにそれを使用します。 .

于 2013-11-14T08:33:38.147 に答える
1

Qt についてはよくわかりませんが、これはselect()単一のスレッドで複数のソケット アクセスを多重化するために使用する典型的なシナリオである可能性があります。

選択用のスレッドが主にソケットとの間のデータの処理に使用される場合、非常に高速になります (コンテキスト スイッチが少なくなるため)。したがって、非常に大量のデータを転送しない場合は、シングル スレッド ソリューションの方が高速になる可能性があります。

そうは言っても、私はあなたのニーズに最も適したソリューションを使用します.かなりの時間で実装できるものです. (非同期) の実装selectは非常に面倒で、必要のない過剰な作業になる可能性があります。

これはCのようなアプローチですが、とにかくお役に立てば幸いです。

于 2013-11-14T09:04:33.647 に答える