最近の通常のパターンは、ブロッキング IO を別のスレッドで実行し、メイン スレッドで実行されるコールバック/オブザーバーを使用するようです。このパターンは、すべての GUI 作業をメイン スレッドで実行するという最新のベスト プラクティスとうまく調和します。
編集:
申し訳ありませんが、サーバーが C++ であることを見逃していました。
明確にするために...
クライアント側には 2 つのスレッドがあります。GUI と対話用のメイン スレッド、および接続が確立されたときに生成された通信スレッド。2 つのスレッドは、「コールバック」または実際のオブザーバーのいずれかを意味するオブザーバー デザイン パターンの変形を使用して通信します。これにより、メイン スレッドは GUI をフリーズすることなく続行できます。通信スレッドが呼び出したときに、何らかの方法でその呼び出しがメイン スレッドにディスパッチされることを確認してください。
サーバー側では、通常、同じパターンのいくつかのバリエーションがあります。接続をリッスンし、作成された接続ごとにスレッド (またはプロセス) を生成するマスター スレッドが存在します。通信スレッドは、セッションが存続している限り存続します。これにより、通信スレッドは、メイン スレッドが新しい接続を受け入れないようにすることなく、ブロッキング呼び出しを行うことができます。
まったく同じ考えです。
特にサーバー側では、多くのバリアントがあります。ポイントは通常、リソースを節約し、作業のやり直しを避けることです。したがって、許可されるスレッドの数を制限し、おそらくそれらを再利用したいと考えます (「スレッド プール」)。
C++ で正確にどのように行うかについては、簡単に答えられる質問ではありません。C# や Java などの最新の言語には、これを行う明確な方法がありますが、C++ はこの点にとらわれません。「C++」の回答はありませんが、「C++ on Windows」の回答があります。Windows の専門家ではないので、ここでお手伝いすることはできません。