11

私はアプリで GKMatch をかなり長い間使用してきました。私は追跡しており、ゲームが時々停止するという問題を抱えており、パケットが送信されているが受信されていないことを突き止めました. これはたまにしか発生しませんが、なぜ発生するのかを追跡できないようです。

すべてのメッセージは GKSendDataReliable を使用して送信されます。

ロギングは、パケットが 1 つのデバイスから正常に送信されていることを示していますが、ターゲット デバイスでは決して受信されません。

//Code sample of sending method....
//self.model.match is a GKMatch instance    
-(BOOL) sendDataToAllPlayers:(NSData *)data error:(NSError **)error {
        [self.model.debugger addToLog:@"GKManager - sending data"];
        return [self.model.match sendDataToAllPlayers:data withDataMode:GKSendDataReliable error:error];
    }

...

//Code sample of receiving method....
// The match received data sent from the player.
-(void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {
    [self.model.debugger addToLog:@"GKManager - received data"];
    [super didReceiveData:data fromPlayer:playerID];
}

私が見ているのは、「sendDataToAllPlayers」メソッドから定期的に (おそらく 100 件のメッセージに 1 件) 送信されますが、受信デバイスが「didReceiveData」メソッドにヒットすることはありません。私の理解では、GKSendDataReliable を使用するとメッセージが送信され、確認を受信するまで別のメッセージは送信されません。メッセージは受信されませんが、同じデバイスから新しいメッセージが送信されます。

送信メソッドは「YES」を返し、エラーはゼロですが、didReceiveData はヒットしません...!

誰もこれを見たことがありますか?誰にもこれが何であるか考えがありますか? これをデバッグするために他に何ができるかわかりません。

4

2 に答える 2

8

バグを確認しました。問題を一貫して再現するサンプル プロジェクトを作成しました: https://github.com/rabovik/GKMatchPacketLostExample。弱いインターネット接続 (Wi-Fi を搭載した iPad 3 と EDGE を搭載した iPhone 4S、どちらも iOS 6.1.3) でテストしたところ、Game Center API からのエラーなしで定期的に一部のパケットが失われました。さらに、デバイスがデータの受信を停止することがありますが、別のデバイスはメッセージを正常に送受信します。

したがって、バグが存在することが確実な場合、可能な唯一の回避策は、真に信頼できる配信のためにトランスポート層を追加することです。

この目的のために簡単な lib を作成しました: https://github.com/rabovik/RoUTP。送信されたすべてのメッセージを受信ごとに確認するまで保存し、失われたメッセージを再送信し、シーケンスが壊れた場合に受信したメッセージをバッファリングします。私のテストの組み合わせでは、「RoUTP + GKMatchSendDataUnreliable」は「RoUTP + GKMatchSendDataReliable」よりもさらにうまく機能します(もちろん、実際には信頼できない純粋な GKMatchSendDataReliable よりも優れています)。

于 2013-07-06T13:13:58.587 に答える
1

[編集: iOS9 では RoUTP が正しく動作しないようです]

昨日、パケット損失が発生している Wi-Fi の範囲の端でいくつかのテストを行いました。GKMatchSendDataReliable を使用してパケットが失われると、プレイヤーは GKMatch セッションから突然切断されます。match:player:didChangeState が GKPlayerStateDisconnected で呼び出され、プレーヤーの ID が playerIDs ディクショナリから削除されます。これは、ほんのわずかなパケット損失で発生します。たとえば、この接続からインターネットを閲覧できます。

ここで、信頼性の低いパケットの送信に切り替えると、match:player:didChangeState が起動することはなく、試合は問題なく続行されます (重要なパケットが時々失われることを除いて)。パケット損失がかなり大きくなった場合にのみ切断されます。ここで、Yan の RoUTP ライブラリが便利です。わずかなパケット損失が発生した場合でも、プレーヤーを切断することなく、これらの重要なメッセージを追跡して再試行できるからです。

また、GKMatchSendDataReliable を使用したデータ送信は、メッセージが配信のために正常にキューに入れられた場合にのみ YES を返します。メッセージが正常に配信されたかどうかはわかりません。どうして?それはすぐに戻ります。

于 2014-11-10T15:16:42.410 に答える