Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/97.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 游戏中心GKMatch GKSendDataReliable数据包丢失_Ios_Game Center_Multiplayer_Gksession - Fatal编程技术网

Ios 游戏中心GKMatch GKSendDataReliable数据包丢失

Ios 游戏中心GKMatch GKSendDataReliable数据包丢失,ios,game-center,multiplayer,gksession,Ios,Game Center,Multiplayer,Gksession,我已经在一个应用程序中成功地使用GKMatch很长一段时间了。我一直在追查和问题的游戏偶尔停止,并已跟踪到数据包被发送,但没有收到。这种情况只是偶尔发生,但我似乎无法找到它发生的原因 所有消息都使用GKSendDataReliable发送 日志记录显示数据包正从一个设备成功发送,但目标设备从未接收到数据包 //Code sample of sending method.... //self.model.match is a GKMatch instance -(BOOL) sendDat

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

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

发送方法返回“是”,错误为零,但从未命中didReceiveData

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

我确认了这个错误。 我制作了一个示例项目,不断地复制问题:。我在一个弱的互联网连接上测试了它(iPad3带有Wi-Fi和iPhone4S带有EDGE;都在iOS 6.1.3上),一些数据包经常丢失,而游戏中心API没有任何错误。此外,有时设备停止接收任何数据,而另一个设备仍然成功地发送和接收消息

因此,如果我们确信该缺陷存在,唯一可能的解决方法是添加一个额外的传输层,以实现真正可靠的传输

为此,我编写了一个简单的lib:。它保存所有发送的消息,直到确认每个接收到的消息,重新发送丢失的消息,并在序列中断的情况下缓冲接收到的消息。
在我的测试中,“RoUTP+GKMatchSendDataReliable”组合的效果甚至比“RoUTP+GKMatchSendDataReliable”更好(当然比真正不可靠的纯GKMatchSendDataReliable更好)。

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

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

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


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

我的用户还抱怨某些数据可能在游戏过程中意外丢失。但我自己仍然无法复制这个错误。您是否有一个示例项目,其中此错误始终是可复制的?如果是,请分享(可能在github上)?谢谢。我的项目非常大(目前商店中有活动应用程序),但我会尝试将其放在一个较小的版本中,看看它是否可以持续复制。我也有同样的问题,尤其是当其中一台设备上的互联网连接较弱时。GKSendDataReliable在收到确认之前是否会停止发送消息?您是否为此提交了错误报告?这似乎从根本上破坏了功能,应该会影响任何使用实时匹配的开发人员。我也证实了这一点。苹果真的非常令人惊讶(更不用说令人失望了)。可靠模式的全部要点是,连接应该缓冲和延迟,直到它能够发送,而不仅仅是丢弃消息。嘿,我一直在做一个非常复杂的rts游戏,我已经注意到了你所描述的问题。你建议我试试RoUTP库吗?它确实有效,但非常基本。例如,一旦您开始使用RoUTP,所有数据包都必须通过RoUTP发送。而且它将永远尝试传递数据包。这可能导致突发的延迟数据包一次全部通过。我可以考虑使用全客户端服务器来代替对等和开沟例程。如果客户端出现数据包丢失并断开连接,那么这可能只是为其他客户端保持游戏正常的一个期望结果,而不是让玩家突然出现在现场杀死其他玩家,然后任何人都会因为数据包涌入而做出反应。它也没有说明在信息丢失时谁发送了什么数据包。因此,必须使用char数组将playerID编码到消息中。所有玩家都会收到所有消息,所以若你们使用客户端服务器,那个么这并不理想。也就是说,您不能向特定玩家发送消息。只发送给所有玩家,然后让玩家忽略不针对他们的消息。嘿,谢谢回复。因此,我最初发送的数据包是可靠的,但由于Game Center处理与可靠数据包断开连接的方式,我需要尝试其他方法,因为即使最小的超时也会断开用户的连接。因此,我最终做的是在发送消息不可靠上编写自己的层,并自己管理可靠队列。这使我能够将某些消息优先于其他消息,并在不再需要它们时手动丢弃数据包(即,如果花费的时间太长)。到目前为止,我在这方面取得了成功。并且没有发生断开连接
//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];
}