ネットワーク経由でさまざまな種類のデータ (ビデオ ストリーム、オーディオ ストリーム、サービス通知など) を送信するクライアント サーバー Winsock アプリ (Visual C++) を開発しています。よりクリーンなアプローチは、個々のデータ型ごとに個別のスレッドで個別のポートを使用することであることを知っています (ここでは「ストリーム」と呼びます)。ただし、これには少なくとも 5 つの異なるポートを占有する必要があり、一部のネットワーク インフラストラクチャ (ファイアウォール ポート フォワーディングなど) で問題が発生する可能性があります。
だから私は1ポート接続(TCP)を実装しようとしています.1つのソケットだけが異なるストリームを送信するために使用されます. 個々のパケットには、それが属するストリーム、予想される合計メッセージ サイズなどを示す情報がヘッダーに含まれます。5 つの異なるストリームがあるとします。同じソケットのsend()を呼び出すために 5 つのスレッドを使用する予定です。これは安全ですか?異なるストリームからのパケットが混在して到着することはわかっていますが、送信された各パケットに必要なメタ情報を含めると、反対側で適切に再構築できますよね?
しかし、本当の問題は受信側です。同じソケットで複数のスレッドからsend()を呼び出すことはおそらく問題ありませんが (よくわかりませんので確認が必要です!)、複数のスレッドからrecv()を呼び出すことはあまり意味がありません。したがって、1 つのスレッドから 1つのブロッキングrecv()を使用する必要があります。しかし、パケット ヘッダー (特定のパケットが属しているストリームを特定する) に基づいて、異なるスレッドで処理をフォークする必要があります。ビデオ ストリームは 1 つのスレッド、サウンド ストリーム - 別のスレッドなどで処理する必要があります。パフォーマンスが最優先事項であるため、すべてのストリームを 1 つのスレッドで処理することは考えられません。
要約すると、次の 3 つの質問があります。
- 複数のスレッドから同じソケットに対してsend()を呼び出しても問題ありませんか? (どの送信側スレッド (つまり、サブシステム) に属しているかに関する情報がパケット ヘッダーに含まれていると仮定します)。
- 受信側に1 つのブロッキングソケットを持ち、単一のスレッドからループ内でrecv()を呼び出すと、異なる論理ストリームの受信パケットを異なるワーカー スレッドに「フォーク」する方法は?
- 1 つのポートを介して複数のストリーム転送を実装するための追加の推奨事項は何ですか?
PS: 確かに、1 つのポートを複数のソケットで使用する方法はありませんね。
それは、Windows プラットフォーム、Winsock2、Visual C++ です (プラットフォーム固有の素晴らしいヒントを提供できれば)。
=更新=
「ソケットをロックする」とは、send()関数へのアクセスをシリアル化するということですか? たとえば、クリティカル セクションで?
受信側については...メッセージを組み立てると思います(ビデオフレームやサウンドサンプルなどの論理的な完全なデータ構造を「メッセージ」と呼びます)。個々のストリームを個々のバッファーに)、次に、組み立てられたメッセージを (メッセージが完全に受信されたときに) フォーク スレッドに渡します。それが問題です - それらを渡す方法。私が考えた 1 つの方法は、イベント オブジェクトです。レシーバー スレッドからSetEvent()を呼び出して、 WaitForSingleObject()をトリガーします。(これはいくつかのループにあります)異なるスレッドで。これが許容できる解決策であるかどうかアドバイスできますか? もっと良いものを提案できますか?これを行う (同じアプリケーションの別のスレッドを「トリガー」する) ためのより高速なソリューションは、イベント オブジェクトよりもありませんか? そして、どのようにデータを渡すのですか?