5

ゲーム キット フレームワークを介してアプリを実行している他の iPhone とデータを交換するアプリを作成しようとしています。iPhone はお互いを検出して正常に接続しますが、データを送信すると問題が発生します。NSString をシリアル化し、接続を介して送信すると、相手側で問題なく出力されるため、iPhone が正しく接続されていることがわかります。しかし、(NSKeyedArchiver を使用して) 大きなオブジェクトをアーカイブしようとすると、「AGPSessionBroadcast に失敗しました (801c0001)」というエラー メッセージが表示されます。

これは、送信するデータが大きすぎるためだと思います (私のファイルのサイズは約 500k ですが、Apple は最大 95k を推奨しているようです)。データをいくつかの転送に分割しようとしましたが、もう一方の端で適切にアーカイブ解除することはできません。他の誰かがこの問題に遭遇したかどうか、そしてあなたがそれをどのように解決したか疑問に思っています。

4

2 に答える 2

5

私は300K前後のファイルで同じ問題を抱えていました。問題は、次のチャンクを送信する前に、受信者がいつパイプを空にしたかを送信者が知る必要があることです。

最終的に、両側で実行される単純な状態エンジンになりました。送信者は、送信される合計バイト数とパケット サイズを含むヘッダーを送信し、反対側からの確認応答を待ちます。ハンドシェイクを取得すると、シーケンス番号がスタンプされた固定サイズのパケットの送信に進みます。

受信者はそれぞれを取得し、それを読み取ってバッファに追加し、取得したパケットをシーケンス # でパイプに書き戻します。送信者はパケット # を読み取り、別のバッファの価値をスライスします。各側は、現在の状態 (アイドル、ヘッダーの送信、ヘッダーの受信、データの送信、データの受信、エラー、完了など) を追跡します。フル バッファ サイズよりも小さい可能性があります。

これは (少し遅いですが) 正常に動作し、任意のサイズにスケーリングできます。5K のパケット サイズから始めましたが、かなり遅くなりました。10K にプッシュしましたが、問題が発生し始めたので、取り下げて 8096 に保持しました。バイナリ データとテキスト データの両方で問題なく動作します。

于 2009-08-22T06:24:15.493 に答える
3

GameKitは一般的なファイル転送APIではないことに注意してください。これは、プレーヤーの場所、現在の場所、その他のオブジェクトなどを更新するためのものです。したがって、一般的な共有メカニズムのAPIを乗っ取るのは理解できますが、ゲームに300kを送信するのは賢明ではないようです。

問題は、それがTCP接続ではないということです。それはUDP(データグラム)接続です。このような場合、データはストリーム(TCPによってパケット化される)ではなく、データの巨大なチャンクです。(技術的には、UDPは複数のIPパケットにフラグメント化できますが、そのうちの1つが失われ、TCPが再試行するのとは対照的に、UDP全体が失われます)。

ほとんどの有線ネットワークのMTUは約1.5kです。Bluetoothの場合、約0.5kです。したがって、送信したUDPパケットは、(a)失われる可能性があり、(b)複数のMTUサイズのIPパケットに分割される可能性があり、(c)これらのパケットの1つが失われると、セット全体が自動的に失われます。

あなたの最善の戦略はTCPをエミュレートすることです-それはシーケンス番号でパケットを送信します。受信側は、後で失われたパケットの重複送信を要求できます。NSKeyedArchiverと同等のものを使用している場合、1つの提案は、キーを反復処理し、それらを個別のキーとして書き出すことです(各キー値がそれ自体でそれほど大きくないと仮定します)。返送されるパケットごとに何らかのACKが必要であり、完了したら合計ACKが必要になるため、送信者はデータをメモリからドロップしても問題がないことを認識できます。

于 2009-08-22T07:02:11.410 に答える