重新连接到断开的同伴
我在我的应用程序中使用iOS 7 Multipeer框架,但遇到设备断开连接的问题。 如果我在两个设备(设备A和设备B)中打开应用,则两个设备会自动相互连接。 然而,几秒钟后,设备A从设备B断开。即,首先,连接如下:
A ---> B A <--- B
几秒钟后:
A ---> B AB
设备A维护它的连接,但设备B得到一个MCSessionStateNotConnected。
这意味着A可以向B发送数据,但是B不能应答。 我试图通过检查设备是否连接,如果不是,重新启动连接使用:
[browser invitePeer:peerID toSession:_session withContext:Nil timeout:10];
但是didChangeStatecallback只是用MCSessionStateNotConnected调用。
奇怪的是,如果我发送应用程序A的背景,然后重新打开它,B重新连接到它,并保持连接。
Multipeer API(和文档)似乎有点稀疏,所以我认为它会工作。 在这种情况下,我应该如何重新连接设备?
我遇到了同样的问题,似乎与我的应用程序浏览和广告同时发生,以及两个邀请被发送/接受。 当我停止这样做,并让一个同行相互邀请的设备保持连接。
在我的浏览器委托中,我正在检查发现的对等方的displayName
的哈希值,只有在我的对等方具有较高的哈希值时才发送邀请:
编辑
正如@Masa指出的那样,NSString的hash
值在32位和64位设备上是不同的,所以在displayName
上使用compare:
方法displayName
。
- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info { NSLog(@"Browser found peer ID %@",peerID.displayName); //displayName is created with [[NSUUID UUID] UUIDString] BOOL shouldInvite = ([_myPeerID.displayName compare:peerID.displayName]==NSOrderedDescending); if (shouldInvite) [browser invitePeer:peerID toSession:_session withContext:nil timeout:1.0]; else NSLog(@"Not inviting"); }
正如你所说,文档是稀疏的,所以谁知道苹果真的希望我们做什么,但我已经尝试使用一个会话发送和接受邀请,并为每个接受/发送的邀请创build一个新的会话,但是这特殊的做事方式给了我最大的成功。
对于任何有兴趣的人,我创build了MCSessionP2P ,这是一个演示应用程序,演示了MCSession的ad-hocnetworkingfunction。 该应用程序都在本地networking上宣传自己,并以编程方式连接到可用的对等体,build立一个对等networking。 Hat给@ChrisH提供了一个比较邀请同伴散列值的技巧。
我喜欢ChrisH的解决scheme,它揭示了关键的洞察力,即只有一个对等体应该连接到另一个对等体 ,而不是两个对等体 。 相互连接的尝试会导致相互的断开(尽pipe并不是说单方面的连接实际上是违背直觉的,在状态和通信方面是相互连接的,所以工作正常)。
然而,我认为比一个同伴邀请更好的方法是邀请同伴邀请,但只有一个同伴接受 。 我现在使用这种方法,并且效果很好,因为两个同伴都有机会通过邀请的context
参数将丰富的信息传递给另一个,而不必依赖foundPeer
委托方法中的可用信息。
因此,我build议像这样的解决scheme:
- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info { [self invitePeer:peerID]; } - (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void (^)(BOOL accept, MCSession *session))invitationHandler { NSDictionary *hugePackageOfInformation = [NSKeyedUnarchiver unarchiveObjectWithData:context]; BOOL shouldAccept = ([hugePackageOfInformation.UUID.UUIDString compare:self.user.UUID.UUIDString] == NSOrderedDescending); invitationHandler(shouldAccept && ![self isPeerConnected:peerID], [self openSession]); }
当设备试图同时连接到对方时,我也遇到同样的问题,我不知道如何find一个原因,因为我们没有任何与MCSessionStateNotConnected错误。
我们可以使用一些狡猾的方法来解决这个问题:当应用程序启动时,放入txtlogging(发现信息)一次[[NSDate date] timeIntervalSince1970] 。 谁先开始 – 向别人发送邀请。
但我认为这不是一个正确的方法(如果应用程序在同一时间开始,不太可能… :))。 我们需要找出原因。
这是我向苹果公司报告的一个错误的结果。 我已经解释了如何解决这个问题, 为什么我的MCSession节点会随机断开?
我还没有标记这些问题的合并,因为虽然潜在的错误和解决scheme是相同的,但这两个问题描述了不同的问题。
保存对等体B的哈希。如果没有连接,使用定时器连续检查连接的状态,尝试重新连接每个给定的时间段。
根据苹果文件在使用Multipeer连接时select邀请者 “在iOS 7中,发送同时发送的邀请可能导致两个邀请都失败,导致两个节点之间无法互相通信。
但是iOS 8已经修复了它。