2013-06-07 4 views
11

앱에서 GKMatch를 사용하고 있습니다. 나는 쫓아 다니며 때때로 게임을 중단하고 패킷을 보내지 만 수신하지 못하도록 추적했다. 가끔씩 만 발생하지만 왜 그런 일이 발생했는지 추적 할 수는 없습니다.Game Center 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을 사용하여 메시지를 보내고 승인을받을 때까지 다른 메시지를 보내지 않아야한다는 것입니다. 메시지는 수신되지 않지만 새 메시지는 동일한 장치에서 전송됩니다.

송신 방법이 '예'이고 오류는 nil이지만 didReceiveData는 결코 적중되지 않습니다 ...!

본 사람이 있습니까? 누구나 이것이 어떤 아이디어 일 수 있습니까? 나는 이것을 디버깅하기 위해 내가 무엇을 할 수 있는지 모른다.

+0

내 사용자는 게임 중에 일부 데이터가 실수로 손실 될 수도 있다고 불평합니다. 그러나 나는이 버그를 직접 재현 할 수 없다. 이 버그가 지속적으로 재현 될 수있는 예제 프로젝트가 있습니까? 그렇다면 공유 할 수 있습니까 (기저귀에있을 수 있음)? 감사. – 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에서 오류없이 정기적으로 손실됩니다. 또한 때로는 장치가 데이터 수신을 중지하고 다른 장치는 여전히 메시지를 성공적으로 보내고받습니다.

버그가있는 것으로 확신하는 경우 유일한 대안은 신뢰할 수있는 전송을 위해 추가 전송 레이어를 추가하는 것입니다.

이 목적을 위해 간단한 lib를 작성했습니다 : https://github.com/rabovik/RoUTP. 각 수신 메시지에 대한 확인 응답이 수신 될 때까지 모든 전송 된 메시지를 저장하고 끊어진 시퀀스가 ​​발생할 경우 수신 된 메시지를 버퍼에 다시 보냅니다. 내 테스트 조합에서 "RoUTP + GKMatchSendDataUnreliable"은 "RoUTP + GKMatchSendDataReliable"보다 더 효과적입니다. 물론 순수 GKMatchSendDataReliable보다 신뢰성이 좋습니다.

+0

RooSp가 iOS 9에서 깨진 것 같습니다. 모든 데이터를 사용하여 데이터를 보내면 모든 데이터가 수신되지는 않습니다. 신뢰할 수 있거나 신뢰할 수없는 운송 수단을 사용하더라도 문제가되지 않습니다. RoUTP를 비활성화하면 모든 것이 잘 작동합니다. –

1

: 나는 패킷 손실이 발생하는 한 내 무선 랜의 범위의 가장자리에 어제 몇 가지 테스트를했다

[편집 RoUTP 더 이상 iOS9에서 제대로 작동하는 것 같다]. GKMatchSendDataReliable을 사용하여 패킷이 손실되면 플레이어가 GKMatch 세션에서 갑자기 분리됩니다. match : player : didChangeState가 GKPlayerStateDisconnected와 함께 호출되고 playerID가 playerIDs 사전에서 제거됩니다. 이것은 약간의 패킷 손실로 발생합니다. 예를 들어이 연결에서 여전히 인터넷을 탐색 할 수 있습니다.

패킷을 신뢰할 수없이 보내는 것으로 전환하면 다음과 일치시킵니다. player : didChangeState가 실행되지 않고 일치가 문제없이 계속됩니다 (중요 할 수있는 가끔 패킷 손실 제외). 패킷 손실이 상당 해지면 연결이 끊어집니다. 이제는 Yan의 RoUTP 라이브러리가 유용합니다. 플레이어가 약간의 패킷 손실이있을 때 연결을 끊지 않고도 중요한 메시지를 추적하고 다시 시도 할 수 있기 때문입니다.

또한 GKMatchSendDataReliable을 사용하여 데이터를 보내면 메시지가 성공적으로 배달 대기중인 경우에만 YES가 반환됩니다. 메시지가 성공적으로 배달되었는지 여부는 알려주지 않습니다. 어떻게 그럴 수 있니? 바로 돌아온다.

+0

안녕하세요, 나는 꽤 복잡한 rts 게임을 작업 해왔고, 당신이 묘사하고있는 문제를 정확히 알아 봤습니다. RoUTP 라이브러리를 사용해 보시 겠어요? –

+0

확실히 작동하지만 매우 기본입니다. 예를 들어, 일단 모든 패킷을 사용하기 시작하면 RoUTP를 통해 모든 패킷을 보내야합니다. 그리고 그것은 패킷을 영원히 전달하려고 노력할 것입니다. 이로 인해 지연된 패킷이 한 번에 모두 전달 될 수 있습니다. 필자는 피어 투 피어 (peer to peer) 대신에 전체 클라이언트 서버로 이동하고 RoUTP를 버리는 것을 고려할 수 있습니다. 클라이언트가 패킷 손실이 있고 연결이 끊어지면 패킷이 급증하여 다른 플레이어가 반응하기 전에 다른 플레이어를 죽이는 장면을 플레이어가 튕기지 않고 다른 클라이언트의 게임을 정상적으로 유지하려는 바람직한 결과 일 수 있습니다. –

+0

It 또한 그 정보가 누락되면 누가 어떤 패킷을 보내는 지 말하지 않습니다. 따라서 char 배열을 사용하여 메시지에 playerID를 인코딩해야합니다. 모든 플레이어는 모든 메시지를 수신하므로 클라이언트 서버로 이동하면 이상적이지 않습니다. 즉, 특정 플레이어에게 메시지를 보낼 수 없습니다. 모든 플레이어에게만 해당 메시지를 보내지 마세요. –