ios - 禁用 WiFi 的多点连接

标签 ios objective-c cocoa-touch multipeer-connectivity

我已经阅读了文档,但没有太多有关选择对等点连接的可能介质的多点连接信息。

多点连接自动发现基于 WiFi 或蓝牙的对等点。有没有办法将其限制为仅限蓝牙?

最佳答案

正如 @kdogisthebest 正确指出的那样,没有办法强制 Multipeer Connectivity 使用特定的网络技术,但由于您的问题与 WiFi 的特定问题有关,所以这个答案详细说明了我正在采取的解决方法.

我通过在创建 MCNearybyServiceAdvertiser 时在 discoveryInfo 中发送缩短的时间戳来解决 WiFi 上的“幻影”对等点问题。这里有几个注意事项:

1) 此解决方案假设两个设备具有相同的时间。我通过使用 ios-ntp 的修改版本来确保这一点作为应用程序的时间源。

2) 它还假设广告和浏览不会运行太长时间。我将发现阶段的时长设置为 60 秒,并且每次重新启动时我都会完全重新初始化浏览器/广告商。

3) MPC 似乎不喜欢 discoveryInfo 中包含太多字节,因此基于纪元发送 NSTimeInterval 不起作用。我不得不截断它们。

因此,当我的应用程序进入发现模式时,它会同时开始浏览和广告。广告代码如下:

- (void)startAdvertising {

    if (_advertising){
        NSLog(@"Already advertising");
        return;
    }

    self.acceptedPeerIDNameMap = [NSMutableDictionary dictionary];

    NSInteger timeStamp = [self shortenedNetworkTimeStamp];
    NSDictionary *discoveryInfo = @{kAdvertisingDiscoveryInfoTimestampKey:[NSString   stringWithFormat:@"%ld",(long)timeStamp]};

    NSLog(@"Starting advertiser");

    self.serviceAdvertiser = [[MCNearbyServiceAdvertiser alloc] initWithPeer:_myPeerID
                                                           discoveryInfo:discoveryInfo
                                                             serviceType:kServiceType];
    _serviceAdvertiser.delegate = self;

    [_serviceAdvertiser startAdvertisingPeer];

    self.advertising = YES;
}

方法 shortenedNetworkTimestamp 仅采用 NSTimeInterval(使用 ntp 框架或 timeIntervalSinceReferenceDate 并从中删除 1400000000

然后,当浏览器发现对等点时,它会检查广告商的时间戳是否在已知的发现持续时间内(在我的例子中为 60 秒):

- (void)browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info {

    DLog(@"Browser found peer ID %@",peerID.displayName);

    //Only one peer should invite the other
    BOOL shouldInvite = [peerID.displayName compare:_myPeerID.displayName]==NSOrderedAscending;

    //Don't re-send invitations
    if (_peerInfoDisplayNameMap[peerID.displayName]){
        DLog(@"Already connected to peerID %@",peerID.displayName);
        shouldInvite = NO;
    }
    else if (_invitedPeerIDNameMap[peerID.displayName]){
            DLog(@"Already invited peerID %@",peerID.displayName);
            shouldInvite = NO;
    }

    //Invite if discovery info is valid
    if (shouldInvite && [self discoveryInfoIsValid:info]) {

        DLog(@"Inviting");

        _invitedPeerIDNameMap[peerID.displayName] = peerID;

        MCSession *session = [self availableSession];
        [_serviceBrowser invitePeer:peerID toSession:session withContext:nil timeout:0];
    }
    else {
        DLog(@"Not inviting");
    }
 }

发现信息有效性检查非常简单 - 只需确保信息中发送的时间戳在发现时间范围内(在我的例子中 kDiscoveryPhaseDuration 为 60 秒):

- (BOOL)discoveryInfoIsValid:(NSDictionary *)info {

    BOOL isValid = YES;

    NSString *infoTimeStamp = info[kAdvertisingDiscoveryInfoTimestampKey];
    NSTimeInterval sentTimeStamp = (infoTimeStamp) ? [infoTimeStamp doubleValue] : -1;
    NSTimeInterval currentTimeStamp = [self shortenedNetworkTimeStamp];

    if (sentTimeStamp==-1 || (currentTimeStamp - sentTimeStamp) > kDiscoveryPhaseDuration){
        DLog(@"Expired discovery info (current=%f, sent=%f)",currentTimeStamp,sentTimeStamp);
        isValid = NO;
    }

    return isValid;
}

希望这有帮助。我在自己的代码中处理了 MPC 中的许多其他怪癖,但我认为上述内容涵盖了这个特定问题。

关于ios - 禁用 WiFi 的多点连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26289811/

相关文章:

ios - 使用 UITableViewCellDeleteConfirmationControl 知道当前单元格的 subview 是什么

iphone - cocos2d-x 应用程序的 HTTP 流量在 Charles 代理中不存在

ios - 使用PhoneGap在iPhone中单击按钮后退出应用程序

ios - SplitViewControllers 可以在 iPhone 上使用吗?

javascript - 从 ObjectiveC 到 ECMAscript

objective-c - IBOutlet 作为属性或作为变量有什么区别?

ios - 创建修改UIButton的方法时出错

ios - 点击已经选中的segment control swift

ios - 使用 iOS 中的通用链接将数据从 App 传回 Safari 网页

ios - 分析显示循环的每次迭代中都有泄漏