非常に高帯域幅のストリーム (たとえば、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() に直接応答する代わりにそれを使用します。 .