11

我在应用程序中成功使用 GKMatch 已经有一段时间了。我一直在追查游戏偶尔停止的问题,并将其追踪到正在发送但未收到的数据包。这只是偶尔发生,但我似乎无法找出它发生的原因。

所有消息都使用 GKSendDataReliable 发送。

日志记录显示数据包从一台设备成功发送,但目标设备从未收到。

//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];
}

我看到的情况是定期(可能 100 条消息中的 1 条)从“sendDataToAllPlayers”方法发送而没有错误,但接收设备从未点击“didReceiveData”方法。我的理解是,使用 GKSendDataReliable 应该发送消息,然后在收到确认之前不会发送另一个消息。未收到消息,但从同一设备发送新消息。

发送方法返回 'YES' 并且错误为 nil,但 didReceiveData 从未命中...!

有没有人见过这个?有谁知道这可能是什么?我不知道我还能做些什么来调试它。

4

2 回答 2

8

我确认错误。我制作了一个示例项目,始终如一地重现该问题:https ://github.com/rabovik/GKMatchPacketLostExample 。我在互联网连接较弱的情况下测试了它(iPad 3 和 Wi-Fi,iPhone 4S 和 EDGE;都在 iOS 6.1.3 上),一些数据包经常丢失,游戏中心 API 没有任何错误。此外,有时设备停止接收任何数据,而另一个仍然成功发送和接收消息。

因此,如果我们确定存在错误,唯一可能的解决方法是添加额外的传输层以实现真正可靠的交付。

为此,我编写了一个简单的库:https ://github.com/rabovik/RoUTP 。它保存所有发送的消息,直到每个接收到的确认,重新发送丢失的消息并缓冲接收到的消息以防序列中断。在我的测试中,“RoUTP + GKMatchSendDataUnreliable”组合比“RoUTP + GKMatchSendDataReliable”效果更好(当然比纯 GKMatchSendDataReliable 更好,后者并不可靠)。

于 2013-07-06T13:13:58.587 回答
1

[编辑:RoUTP 在 iOS9 中似乎不再正常工作]

我昨天在发生丢包的wifi范围边缘进行了一些测试。发生的情况是,当使用 GKMatchSendDataReliable 丢失数据包时,播放器会突然与 GKMatch 会话断开连接。match:player:didChangeState 使用 GKPlayerStateDisconnected 调用,并且玩家的 ID 从 playerIDs 字典中删除。发生这种情况时只有轻微的数据包丢失。例如,我仍然可以从此连接浏览互联网。

现在,如果我切换到不可靠地发送数据包,那么 match:player:didChangeState 永远不会触发,并且比赛会继续没有问题(除了丢失可能很重要的偶尔数据包)。只有当数据包丢失变得很大时,它才会断开连接。现在这就是 Yan 的 RoUTP 库派上用场的地方,因为我们可以跟踪并重试这些重要消息,而不会在玩家遇到轻微丢包时断开连接。

此外,使用 GKMatchSendDataReliable 发送的数据仅在消息已成功排队等待传递时才会返回 YES。它不会告诉您消息是否已成功传递。怎么可能?它立即返回。

于 2014-11-10T15:16:42.410 回答