我在应用程序中成功使用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永远不会被命中......!
有没有人见过这个?有没有人有任何想法这可能是什么?我不知道我还能做些什么来调试它。
答案 0 :(得分: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更好,但这并不可靠)。
答案 1 :(得分:1)
[编辑:在iOS9中,RoUTP似乎不再正常工作]
昨天我在wifi的范围边做了一些测试,丢失了。当使用GKMatchSendDataReliable丢失数据包时,播放器突然与GKMatch会话断开连接。 match:player:使用GKPlayerStateDisconnected调用didChangeState,并从playerIDs字典中删除播放器的ID。这种情况只会发生轻微丢包。我仍然可以通过此连接浏览互联网。
现在,如果我切换到不可靠的发送数据包,那么匹配:player:didChangeState永远不会触发并且匹配继续没有问题(除了丢失偶尔可能很重要的数据包)。只有在数据包丢失变得很大时才会断开连接。现在这是Yan的RoUTP库很方便的地方,因为我们可以跟踪并重试这些重要的消息,而不会让玩家在遇到轻微丢包时断开连接。
此外,如果邮件已成功排队等待传送,则使用GKMatchSendDataReliable发送的数据将仅返回YES。它不会告诉您邮件是否已成功传递。怎么可能呢?它立即返回。