Как @kdogisthebest правильно заявляет, что невозможно использовать Multipeer Connectivity для использования определенной сетевой технологии, но поскольку ваш вопрос относится к конкретной проблеме с WiFi, этот ответ детализирует то, что я делаю, чтобы обойти это.
Я работал вокруг проблемы сверстников «фантомных» через WiFi, отправив укороченную метку времени в discoveryInfo
при создании MCNearybyServiceAdvertiser
. Здесь есть несколько оговорок:
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 (либо с использованием рамок НТПА или 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 есть много других причуд, которые я обрабатываю в своем собственном коде, но я думаю, что вышеупомянутое охватывает эту конкретную проблему.
Просто из любопытства, зачем вам это нужно? – ChrisH
Очень плохо работает с WiFi. Кажется, что уровень кэширования уровня ОС, который, похоже, находит одноранговых узлов, даже когда они сверстники отключены. Я подтвердил это инженером из Apple, который работал над этой штукой. – Legolas
Да, я потратил много времени и сил на решение этой проблемы. – ChrisH