ios 正在重新连接到断开连接的对等方

yb3bgrhw  于 2022-12-05  发布在  iOS
关注(0)|答案(8)|浏览(184)

我正在应用中使用iOS 7 Multipeer框架,但遇到设备断开连接的问题。如果我在两台设备上打开应用:设备A和设备B这两个设备会自动相互连接。但是,几秒钟后,设备A会与设备B断开连接。例如,最初的连接如下所示:

A ---> B
A <--- B

几秒钟后:

A ---> B
A      B

设备A保持其连接,但设备B获得MCSessionStateNotConnected。
这意味着A可以向B发送数据,但B不能回复。我尝试通过检查设备是否已连接来解决此问题,如果未连接,则使用以下命令重新启动连接:

[browser invitePeer:peerID toSession:_session withContext:Nil timeout:10];

但是didChangeState回调只是用MCSessionStateNotConnected调用的。
奇怪的是,如果我将应用程序A发送到后台,然后重新打开它,B重新连接到它,连接保持不变。
Multipeer API(和文档)看起来有点稀疏,所以我假设它会工作。在这种情况下,我应该如何重新连接设备?

4uqofj5v

4uqofj5v1#

我也遇到了同样的问题,似乎是因为我的应用程序同时浏览和广告,以及两个邀请被发送/接受。当我停止这样做,让一个对等体服从另一个邀请时,设备仍然保持连接。
在我的浏览器代理中,我检查发现的对等体的displayName的哈希值,并且仅在对等体具有更高的哈希值时才发送邀请:

编辑

正如@Masa所指出的,NSStringhash值在32位和64位设备上是不同的,因此在displayName上使用compare:方法更安全。

- (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");
    }
}

正如你所说,文档很少,所以谁知道Apple真正希望我们做什么,但我已经尝试过使用单个会话发送和接受邀请,并为每个接受/发送的邀请创建一个新会话,但这种特殊的做事方式给了我最大的成功。

u4vypkhs

u4vypkhs2#

我为感兴趣的人创建了MCSessionP2P,这是一个演示应用程序,展示了MCSession的ad-hoc网络特性。该应用程序既在本地网络上发布自己的广告,又通过编程连接到可用的对等点,建立了一个对等网络。@ChrisH为邀请对等点而比较哈希值的技术值得一提。

iqxoj9l9

iqxoj9l93#

我喜欢ChrisH的解决方案,它揭示了一个关键的观点,即 * 只有一个对等体应该连接到另一个对等体 *,而不是两个都连接。相互连接的尝试会导致相互断开(尽管并不是说单边连接实际上,违反直觉,在状态和通信方面的相互连接,所以这样做很好)。
然而,我认为比一个对等体 inviting 更好的方法是两个对等体都邀请,但只有一个对等体 accept。我现在使用这种方法,效果很好,因为两个对等体都有机会通过邀请的context参数向另一个传递丰富的信息,而不必依赖foundPeer委托方法中可用的少量信息。
因此,我推荐这样一个解决方案:

- (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]);
}
uqxowvwt

uqxowvwt4#

当设备尝试同时相互连接时,我遇到了同样的问题,我不知道如何找到原因,因为我们没有任何关于 MCSessionStateNotConnected 的错误。
我们可以用一些狡猾的办法来解决这个问题:在txt文件中记录(发现信息)应用程序启动的时间 [[NSDate date] timeIntervalSince 1970]。谁先启动-向其他人发送邀请。
但我认为这不是一个正确的方式(如果应用程序在同一时间启动,不太可能...:)。我们需要找出原因。

lnlaulya

lnlaulya5#

这是一个错误的结果,我已经向苹果报告了这个错误。我在回答另一个问题时解释了如何修复它:Why does my MCSession peer disconnect randomly?
我没有将这些问题标记为合并,因为虽然底层bug和解决方案是相同的,但这两个问题描述的是不同的问题。

mwg9r5ms

mwg9r5ms6#

保存对等体B的散列。使用计时器连续检查连接的状态,如果未连接,则尝试在每个给定时间段重新连接。

3bygqnnd

3bygqnnd7#

根据苹果文件Choosing an inviter when using Multipeer Connectivity,“在iOS 7中,同时发送邀请可能会导致两个邀请都失败,使两个对等方无法相互通信。
但iOS 8已经解决了这个问题。

eqoofvh9

eqoofvh98#

It seems that the .notConnected message is a false positive in that the device is still receiving data. So, I manually updated local connection state to .connected
It was hard to factor out other state from other examples. So, I wrote a bare bones MCSession example for SwiftUI, here: MultiPeer

相关问题