You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MCNearbyServiceBrowser邀请陌生Peer卡在MCSessionStateConnecting无法连接

问题根因

按照优先级排序,最可能导致连接卡在MCSessionStateConnecting的原因如下:

  • MCPeerID无效:Multipeer Connectivity框架中,MCPeerID不是仅靠displayName做唯一标识的,内部包含框架生成的唯一标识符。如果你的strangerPeerWithStrangerName方法是根据传入的用户名重新创建了MCPeerID实例,而不是返回扫描时foundPeer回调拿到并存入strangersPeerID数组的原始实例,那么这个新建的PeerID对于浏览器来说是完全无效的,无法匹配到真实扫描到的设备,导致连接无响应。
  • 浏览器未处于活跃扫描状态:MCNearbyServiceBrowser只有在调用startBrowsingForPeers后的活跃状态下,才能向之前发现过的节点发起邀请。如果扫描到陌生人后你调用了stopBrowsingForPeers停止扫描,后续再用同一个浏览器实例发起邀请会直接失效。
  • 对端邀请逻辑拦截:你本地把陌生人标记为好友仅修改了本地状态,对端设备上你仍然属于陌生人,若对端的MCNearbyServiceAdvertiser的didReceiveInvitationFromPeer回调中仅接受好友的邀请,会直接忽略你的邀请请求,你这边就会一直卡在连接状态直到超时。
  • 会话冲突:如果之前和目标节点有未销毁的旧MCSession关联,新建会话发起连接时会出现内部冲突,导致连接无法正常推进。

解决方案

1. 修复MCPeerID获取逻辑

修改strangerPeerWithStrangerName方法,直接从foundPeer回调时存入的strangersPeerID数组中匹配返回原始实例,不要手动新建MCPeerID:

- (MCPeerID *)strangerPeerWithStrangerName:(NSString *)name {
  for (MCPeerID *peer in self.strangersPeerID) {
    if ([peer.displayName isEqualToString:name]) {
      return peer;
    }
  }
  return nil;
}

2. 保证邀请时浏览器处于活跃状态

发起邀请前先检查浏览器状态,未在扫描则先重启扫描,确保邀请请求能正常发出,同时清理旧会话避免冲突:

- (void)strangerDidBecameFriend:(NSString *)newFriend {
  MCPeerID *strangerPeer = [self strangerPeerWithStrangerName:newFriend];
  if (!strangerPeer) return;

  // 确保浏览器处于活跃扫描状态
  if (!self.browser.isBrowsing) {
    [self.browser startBrowsingForPeers];
    // 延迟1秒保证扫描就绪后再发起邀请
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
      [self inviteStrangerPeer:strangerPeer];
    });
  } else {
    [self inviteStrangerPeer:strangerPeer];
  }
}

// 抽离邀请逻辑
- (void)inviteStrangerPeer:(MCPeerID *)peer {
  // 先清理和该节点关联的旧会话
  NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(MCSession *session, NSDictionary *bindings) {
    return [session.connectedPeers containsObject:peer] || session.delegate == self;
  }];
  NSArray *oldSessions = [self.sessions filteredArrayUsingPredicate:predicate];
  for (MCSession *oldSession in oldSessions) {
    [oldSession disconnect];
    [self.sessions removeObject:oldSession];
  }

  MCSession  *session = [[MCSession alloc] initWithPeer:self.sharerPeer
                                       securityIdentity:nil
                                   encryptionPreference:MCEncryptionNone];
  [session setDelegate:self];
  [self.sessions addObject:session];
  [self.browser invitePeer:peer toSession:session withContext:nil timeout:10];
}

3. 调整对端邀请处理逻辑

对端收到邀请时不要直接拦截陌生人请求,可以在邀请的context参数中携带自己的用户标识,对端收到邀请后先校验用户身份,若属于待同意的好友申请则直接调用invitationHandler(YES, session)同意连接。

4. 补充校验回调

实现MCSession的证书校验回调,即使使用无加密模式也主动返回同意,避免框架默认校验拦截连接:

- (void)session:(MCSession *)session didReceiveCertificate:(NSArray *)certificate fromPeer:(MCPeerID *)peerID certificateHandler:(void (^)(BOOL))certificateHandler {
  certificateHandler(YES);
}

内容的提问来源于stack exchange,提问作者Mingxian Zhao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 15:27:02