1

マルチプレイヤー iOS ゲームを作成していて、次の問題に遭遇しました: カスタム オブジェクトの配列を含む辞書を送信します。これらのカスタム オブジェクトは に準拠していNSCodingます。辞書をNSData次のように変換します。

 NSData *data = [NSKeyedArchiver archivedDataWithRootObject:packet];

そしたら送って

[asyncSocket writeData:data withTimeout:-1 tag:tag];

受け取る

[sock readDataWithTimeout:-1 tag:tag];

そして解凍してみる

NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:data];

すべてが非常に単純に見えますが、データの解凍中にアプリがクラッシュし、次のエラーが表示されます

[NSKeyedUnarchiver initForReadingWithData:]: 理解できないアーカイブ (0x62、0x70、0x6c、0x69、0x73、0x74、0x30、0x30)'

送受信されたデータの説明を調べたところ、データが 1) 変更され、2) 切り捨てられて受信側デバイスに送信されることがわかりました。

GameKit プロトコル、Game Center、および bluetooth を介してまったく同じデータを送信すると、このような問題はありません。データを変更せずに受信するため、明らかに問題は GCDAsyncSocket の奥深くにあります。

誰もそのようなトラブルに遭遇したことがありますか?ありがとう

4

1 に答える 1

3

これは、次の理由によるものです。TCPプロトコルは、無制限の長さの単一の連続ストリームの概念に基づいてモデル化されています。dataある種のターミネーターインジケーターに 追加するか、readDataToDataメソッドを使用する必要があります。dataまたは、の長さのインジケーターを接頭辞として付ける必要がありますdata。したがって、readDataWithTimeoutを使用すると、着信TCPストリームから正確なバイト数を抽出できます。

GCDAsynsSocketの作者によるターミネーターの使用例:

NSString *welcomeMsg = @"Welcome to the AsyncSocket Echo Server\r\n";
    NSData *welcomeData = [welcomeMsg dataUsingEncoding:NSUTF8StringEncoding];

    [newSocket writeData:welcomeData withTimeout:-1 tag:WELCOME_MSG];

    [newSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:0];

GameKitプロトコルがすべてを処理するため、GameKitで上記のすべてを実行する必要がない理由。

于 2012-08-06T10:44:52.490 に答える