2013-06-07 5 views
11

Я довольно давно использую GKMatch в приложении. Я преследовал и выпускал игру, периодически останавливаясь и отследив ее до отправки пакетов, но не полученных. Это происходит только изредка, но я не могу понять, почему это происходит.Игровой центр GKMatch GKSendDataReliable потерянный пакет

Все сообщения отправляются с использованием 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]; 
} 

Что я вижу случиться, что периодически (возможно, 1 в 100 сообщениях) отправляется без ошибок от метода «sendDataToAllPlayers», но приемное устройство никогда не попадает в " метод didReceiveData. Я понимаю, что использование GKSendDataReliable должно отправлять сообщения, а затем не будет отправлять другой, пока не получит подтверждение. Сообщения не принимаются, но новые сообщения отправляются с одного устройства.

Метод отправки возвращает «ДА», а ошибка равна нулю, но didReceiveData никогда не попадает ...!

Кто-нибудь когда-либо видел это? Есть ли у кого-нибудь идеи, что это может быть? Я не знаю, что еще я мог сделать, чтобы отладить это.

+0

Мои пользователи также жалуются, что некоторые данные могут быть случайно потеряны во время игры. Но я все еще не могу воспроизвести эту ошибку самостоятельно. У вас есть пример проекта, где эта ошибка постоянно воспроизводится? Если да, не могли бы вы поделиться им (может быть, на github)? Благодарю. – Yan

+0

Мой проект очень большой (активное приложение в магазине в настоящее время), но я попытаюсь собрать меньшую его версию, чтобы убедиться, что она постоянно воспроизводима. –

+1

У меня такая же проблема, особенно когда подключение к Интернету на одном из устройств слабое. Правда ли, что GKSendDataReliable перестает отправлять сообщения, пока не получит подтверждение? – jyek

ответ

8

Я подтверждаю ошибку. Я сделал примерный проект, последовательно воспроизводящий проблему: https://github.com/rabovik/GKMatchPacketLostExample. Я тестировал его на слабом интернет-соединении (iPad 3 с Wi-Fi и iPhone 4S с EDGE, как на iOS 6.1.3), так и некоторые пакеты регулярно теряются без ошибок в Game Center API. Более того, иногда устройство перестает получать какие-либо данные, в то время как другой по-прежнему отправляет и принимает сообщения успешно.

Так что если мы уверены, что ошибка существует, единственным возможным обходным путем является добавление дополнительного транспортного уровня для действительно надежной доставки.

Я написал простую библиотеку для этой цели: https://github.com/rabovik/RoUTP. Он сохраняет все отправленные сообщения до тех пор, пока не будет получено подтверждение для каждого полученного, отправленного сообщения об утере и буферов полученных сообщений в случае нарушения последовательности. В моих тестах комбинация «RoUTP + GKMatchSendDataUnreliable» работает даже быстрее, чем «RoUTP + GKMatchSendDataReliable» (и, конечно, лучше, чем чистый GKMatchSendDataReliable, который не очень надежный). не

+0

RoUTP, похоже, теперь сломан с iOS 9. Если я отправил данные, используя его, не все устройства получат данные. Не имеет значения, пользуюсь ли я надежным или ненадежным транспортом. Если я отключу RoUTP, все будет хорошо. –

1

[Edit: RoUTP уже не кажется правильной работы в iOS9]

вчера я сделал некоторые испытания на краю диапазона моего WiFi, где потеря пакетов была встречающихс. Случается, что когда пакеты теряются с помощью GKMatchSendDataReliable, игрок внезапно отключается от сеанса GKMatch. match: player: didChangeState вызывается с GKPlayerStateDisconnected, а идентификатор игрока удаляется из словаря playerID. Это происходит с небольшой потерей пакетов. Например, я могу просматривать Интернет из этого соединения.

Теперь, если я переключусь на отправку пакетов неудовлетворительно, то сопоставьте: player: didChangeState никогда не срабатывает, и совпадение продолжается без проблем (за исключением потери случайного пакета, который может быть важен). Он будет отключен, только если потеря пакетов станет существенной. Теперь здесь удобна библиотека RootP Yan, поскольку мы можем отслеживать и повторять эти важные сообщения, не отключая наших игроков, когда они сталкиваются с небольшой потерей пакетов.

Кроме того, передача данных с использованием GKMatchSendDataReliable вернет YES только в том случае, если сообщение было успешно поставлено в очередь для доставки. Он не сообщает вам, было ли сообщение успешно доставлено. Как это могло быть? Он сразу возвращается.

+0

Эй, я работал над довольно сложной rts-игрой, и я точно заметил проблему, которую вы описываете. Вы рекомендуете попробовать библиотеку RoUTP? –

+0

Он определенно работает, но это очень просто. Например, все пакеты должны быть отправлены через RoUTP, как только вы начнете его использовать. И он будет продолжать пытаться доставлять пакеты навсегда. Это может вызвать всплеск пакетов с задержкой, которые должны пройти все сразу. Я могу подумать о том, чтобы полный клиентский сервер вместо однорангового узла и канавы RoUTP. Если у клиентов есть потеря пакетов и их отсоединение, это может быть просто желательным следствием, чтобы поддерживать игру в нормальном состоянии для других клиентов, вместо того, чтобы игрок мог всплывать вокруг сцены, убивая других игроков, прежде чем кто-либо сможет реагировать из-за того, что пакеты падают. –

+0

Это также не говорит, кто отправляет какой пакет по мере удаления этой информации. Поэтому вам нужно закодировать идентификатор игрока в сообщении, используя массив символов. Все игроки получают все сообщения, поэтому, если вы заходите на клиентский сервер, тогда это не идеально. То есть вы не можете отправлять сообщения определенным игрокам. Только для всех игроков, а затем игроки игнорируют сообщения, не предназначенные для них. –