設計中の iPhone アプリケーション用のサーバー アプリケーションを作成しています。iPhone アプリは C# (MonoTouch) で作成され、サーバーも C# (.NET 4.0) で作成されています。
ネットワーク層に非同期ソケットを使用しています。サーバーにより、2 つ以上の iPhone (「デバイス」) が相互に接続し、データを双方向に送信できるようになります。着信メッセージに応じて、サーバーはメッセージ自体を処理するか、送信デバイスと同じグループ内の他のデバイスにデータを中継します。この決定は、最初にパケットのヘッダーをデコードし、それがどのタイプのパケットであるかを判断することによって行うことができます。
これは、最初の 8 バイトが 2 つの整数、ヘッダーの長さとペイロードの長さ (ヘッダーよりもはるかに長くなる可能性があります) になるようにストリームをフレーミングすることによって行われます。
サーバーは、ソケットから最初の 8 バイトを (非同期で) 読み取るため、2 つのセクションの長さになります。次に、ヘッダー セクションの全長まで再度読み取ります。
次に、ヘッダーを逆シリアル化し、その中の情報に基づいて、残りのデータ (ペイロード) を別のデバイスに転送する必要があるかどうか、またはサーバー自体が処理する必要があるかどうかを確認できます。別のデバイスに転送する必要がある場合、次のステップは、ソケットに入ってくるデータをたとえば 1024 バイトのチャンクで読み取り、受信側デバイスに接続されている別のソケットを介して非同期送信を使用してこれらを直接書き込むことです。
これにより、サーバーのメモリ要件が軽減されます。パケット全体をバッファーにロードしてから、ネットワークを介して受信者に再送信するわけではないからです。
ただし、非同期ソケットの性質上、1 回の読み取りでペイロード全体を受信できるとは限らないため、すべてのバイトを受信するまで読み取りを続ける必要があります。最終宛先に中継する場合、これは、送信者から受信したバイトのチャンクごとに BeginSend() を呼び出し、そのチャンクを一度に 1 チャンクずつ受信者に転送することを意味します。
これに関する問題は、非同期ソケットを使用しているため、別のスレッドが同じ受信者 (したがって同じ最終宛先ソケット) で同様の操作を実行する可能性が残り、両方のスレッドからのチャンクが発生する可能性が高いことです。混乱して、その受信者に送信されるすべてのデータが破損します。例: 最初のスレッドがチャンクを送信し、送信者からの次のチャンクを待機している場合 (それを中継できるようにするため)、2 番目のスレッドはデータのチャンクの 1 つを送信し、最初のスレッド (および2番目のスレッドのそれについては)データ。
これを書いているとき、ソケット オブジェクトをロックするのと同じくらい簡単なのだろうか?! これは正しいオプションでしょうか、それとも他の問題を引き起こす可能性がありますか (例: リモート デバイスから送り返されているロックされたソケットを介してデータを受信する際の問題?)
前もって感謝します!