views:

498

answers:

1

Hi

I am trying to implement a P2P application. What I try to do is transfer a custom NSObject class's data between the devices. I am not able to figure out when the "receivedData" method is invoked by GKSession.

Here's what I've done

  1. The usual connection and showing a dialog box with peers

  2. When the app receives a state change for a peer and the state is Connected, I am sending the data to all peers (ideally this should be called when each peer accepts the connection) using NSCoding methods

  3. In receivedData, I am decoding the NSData and getting back the NSObject instance

The problem is the session:peer:didChangeState: method is not getting called on both the devices. It just gets called on the device which tapped the "Connect" button in the PeerPicker alert.

Questions

  1. When is didChangeState called and for whom? Shouldn't it be called for each peer when they are connected?

  2. When is the receivedData: method called and for whom? Is it called to confirm receipt of a message (handshake) or just to transmit the data sent by other peers?

Thanks for any help.

+4  A: 

Think of it more as 'master/slave' instead of 'peer to peer.' Presumably both sides have been set up with GameKit and had their delegates assigned. The one side that initiates the connection gets notified via the GKPeerStateConnected state change value that the receiver has accepted the invitation and a connection has been made so it can start sending stuff over.

The receiving side, however, gets its first notice that someone wants to talk to it through the didReceiveConnectionRequestFromPeer delegate method. It saves the session for later use then turns around and calls acceptConnectionFromPeer to accept it. From then on, it gets whatever is sent over through the receiveData method.

The best way to do this is to have a little state-machine that manages what state each side is in. The sender only sends when it's gotten the GKPeerStateConnected event. The receiver is put into connected state once it accepts a connection request so it can do any setup it needs to do before it starts getting data.

Since the network abstraction is GKSession the receiver can then turn around and use the same session instance it got in didReceiveConnectionRequestFromPeer and use it to write back to the sender (who should have its own receiveData method called with responses from the receiver).

The one thing to keep in mind is that there's an implicit data size limit on the buffer you can send through GameKit. You may want to experiment to find what that is for your system (I get something between 5K and 10K--for some reason it varies). You may want to have code to split up your NSData into chunks and manage packetizing/depacketizing the data.

Ramin
Thanks a lot. That clarifies things..
lostInTransit
I hope you work for Apple already. This explanation should be the official docs.
Typeoneerror