views:

171

answers:

1

I've got a peer to peer iPhone game working pretty well. I've created a table to display available peers and I can connect (so far) up to four devices and play a full round of a game from start to finish:

peer picker

But here's my problem...

I create a GKSession on one device with GKSessionModeClient and the other with GKSessionModeServer. The client sees the server, selects to connect it, then the server approves. The server then can tap "start game" when all the peers are connected.

If--before the server starts the game-- the client taps the "back" button to go to the previous screen, the custom peer picker display is popped from the view and the session is "destroyed"...

[_gkSession disconnectFromAllPeers];
[_gkSession setAvailable:NO];
[_gkSession setDelegate:nil];
[_gkSession setDataReceiveHandler:nil withContext:nil];

now, if the client goes back to the peer picker and joins the server again, I get a GKSessionStateConnected state again, but when I sendDataToAllPeers: nothing reaches the client. It works flawlessly if one device starts a game and three devices join and then the server taps "start game". But if someone quits out before the game starts, then recreating a session and joining fails.

Any ideas? My only hack I can think of at this point is preventing a user from tapping "back" once they connect to a server, but that kind of sucks...they'd have to quit the app completely if they changed their mind. I'm at my wits end with this one as the app is running as well as I like it except for this connection issue. Kind of an edge case but I can see a user being annoyed if they can't start a game without having to restart the application to get the sessions cleared.

Will make this a bounty when I can. Please help!

Edit @byteclub

  • Does the server clean up all of the relevant data structures correctly if client leaves before game begins?

If the client leaves the game lobby after the server accepts their connection, the client's session is destroyed:

- (void)destroySession
{
    trace(@"destroySession");

    self.gameDelegate = nil;
    self.lobbyDelegate = nil;

    [_gkSession disconnectFromAllPeers];
    [_gkSession setAvailable:NO];
    [_gkSession setDelegate:nil];
    [_gkSession setDataReceiveHandler:nil withContext:nil];

    [_peerList removeAllObjects];
}

I do not call any disconnectFromPeers methods on the server device though.

* Is the client-disconnect-cleanup procedure different for cases when the

game has been started already?

Slightly, if a client disconnects then everyone receives a "peer quit" notification and the game ends. I don't worry about reconnecting in this case. It's mainly in the game lobby where the client can "Cancel" to go back to the home screen where the problem is. The client's session is destroyed in this case. If they then go back to the lobby and a new GKSession is alloc'ed, they can connect to the server still, but sendDataToAllPeers no longer works once they are connected.

* Do you still have a problem if, before reconnecting, you restart the

client, but leave the server running as is?

The client can reconnect in any case. I can quit, go back, restart the app and reconnect no problem. Just sendDataToPeers fails unless the server and client are both restarted.

* Do you completely destroy GKSession object on the client side

when user taps "back"?

Yes. (see code above)

I realize this is probably insane to debug from afar but if you have any suggestions for what I could look into, I'd appreciate it.

+1  A: 

It works flawlessly if one device starts a game and three devices join and then the server taps "start game". But if someone quits out before the game starts, then recreating a session and joining fails.

If I'm reading this right, it looks like you have the thing working correctly in some cases, but not others. I'd check the logic to make sure client connects/disconnects are handled the same (correct) way every time.

Some questions:

  • Does the server clean up all of the relevant data structures correctly if client leaves before game begins?
  • Is the client-disconnect-cleanup procedure different for cases when the game has been started already?
  • Do you still have a problem if, before reconnecting, you restart the client, but leave the server running as is?
  • Do you completely destroy GKSession object on the client side when user taps "back"?
Byteclub
"if a client disconnects [after game started] then everyone receives a "peer quit" notification and the game ends" - Do you disconnect all of the peers if one of them quits while game is in progress?
Byteclub
"endDataToAllPeers no longer works once they are connected" - does it not work for data delivery to the newly reconnected client or all of the peers (the ones that stayed connected)?
Byteclub
Does this problem also appear if you have only one client peer?
Byteclub
If you want to go deeper into debugging, you might want to run server on your Mac and try sniffing network traffic between server and client using something like Wireshark (previously known as Ethereal)
Byteclub
sendDataToPeers does not work for the newly re-connected client, so I imagine the issue is there. It does happen with one client only. I think sniffing might be my next step. I'm actually thinking at this point it may be the simulator. I just got a second 3gs in the mail *just now* (LOL) so I'm going to try with device to device with no simulator at all (seems to be a touchy spot for GameKit even with 3.1.3). Thanks for the advice!
Typeoneerror