游戏中心GKMatch GKSendData可靠丢包

问题描述 投票:0回答:3

我已经在应用程序中成功使用 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];
}

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

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

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

ios game-center multiplayer gksession
3个回答
8
投票

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

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

我为此目的编写了一个简单的库:https://github.com/rabovik/RoUTP。它会保存所有发送的消息,直到每个接收到的消息得到确认为止,重新发送丢失的消息,并在序列损坏的情况下缓冲接收到的消息。 在我的测试中,组合“RoUTP + GKMatchSendDataUnreliable”甚至比“RoUTP + GKMatchSendDataReliable”效果更好(当然也比不太可靠的纯 GKMatchSendDataReliable 更好)。


1
投票

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

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

现在,如果我切换到不可靠地发送数据包,则 match:player:didChangeState 永远不会触发,并且比赛会继续进行而不会出现问题(除了偶尔丢失可能很重要的数据包)。仅当数据包丢失严重时才会断开连接。现在,这就是 Yan 的 RoUTP 库派上用场的地方,因为我们可以跟踪并重试这些重要消息,而无需让我们的播放器在遇到轻微丢包时断开连接。

此外,如果消息已成功排队等待传送,则使用 GKMatchSendDataReliable 发送数据只会返回 YES。它不会告诉您消息是否已成功发送。怎么可能呢?它立即返回。


0
投票

现在几年过去了...有人知道是否仍然需要使用 RoUTP(我仍在游戏中使用),或者 Apple 最终完成了这项工作并修复了 GKMatchSendDataReliable,因此它可以开箱即用,无需使用丢失数据包,并且没有断开连接?

© www.soinside.com 2019 - 2024. All rights reserved.