web-dev-qa-db-fra.com

Reconnexion à des paires déconnectés

J'utilise le framework iOS 7 Multipeer dans mon application, mais je rencontre un problème de déconnexion des périphériques. Si j'ouvre l'application sur deux appareils: l'appareil A et l'appareil B, les deux appareils se connectent automatiquement. Cependant, après quelques secondes, le périphérique A se déconnecte du périphérique B. (c’est-à-dire qu’il s’agit d’abord de la connexion):

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

Après plusieurs secondes:

A ---> B
A      B

Le périphérique A maintient sa connexion, mais le périphérique B obtient un MCSessionStateNotConnected. 

Cela signifie que A peut envoyer des données à B mais B ne peut pas répondre. J'ai essayé de contourner cela en vérifiant si le périphérique est connecté et si ce n'est pas le cas, en relancant la connexion en utilisant:

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

Mais le rappel didChangeState est simplement appelé avec MCSessionStateNotConnected. 

Étrangement, si j'envoie l'application A en arrière-plan, puis la rouvre, B se reconnecte à celle-ci et la connexion est maintenue. 

L'API Multipeer (et la documentation) semblent un peu clairsemés, donc je partais du principe que cela fonctionnerait. Dans cette situation, comment dois-je reconnecter l'appareil?

30
Ben Smiley

J'avais le même problème, et cela semble avoir été lié à la navigation et à la publicité de mon application en même temps, et à deux invitations envoyées/acceptées. Lorsque j’ai arrêté de le faire et que j’ai laissé l’un d’eux passer à l’autre pour les invitations, les appareils sont restés connectés.

Dans mon délégué de navigateur, je vérifie la valeur de hachage de la variable displayName du homologue découvert et n'envoie une invitation que si mon homologue a une valeur de hachage plus élevée:

Modifier

Comme l'a souligné @Masa, la valeur hash d'une NSString sera différente sur les périphériques 32 et 64 bits. Il est donc plus sûr d'utiliser la méthode compare: sur 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");
    }
}

Comme vous le dites, la documentation est rare, alors qui sait ce que Apple veut vraiment que nous fassions, mais j’ai essayé d’envoyer et d’accepter des invitations à l’aide d’une seule session et de créer une nouvelle session pour chaque invitation acceptée/envoyée. manière particulière de faire les choses m’a donné le plus de succès. 

22
ChrisH

Pour les personnes intéressées, j’ai créé MCSessionP2P , une application de démonstration illustrant les fonctionnalités réseau ad hoc de MCSession. L’application s’annonce elle-même sur le réseau local et se connecte par programme aux homologues disponibles, en établissant un réseau homologue à homologue. Chapeau pointe à @ChrisH pour sa technique de comparaison des valeurs de hachage pour inviter des pairs.

5
Marco

J'ai aimé la solution de ChrisH, qui révèle le principe clé selon lequel un seul pair doit se connecter à l'autre , pas les deux. Les tentatives de connexion mutuelle entraînent une déconnexion mutuelle (bien qu’une connexion unilatérale ne soit pas réellement soit , de manière contre-intuitive, une connexion mutuelle en termes d’état et de communication, de sorte que tout fonctionne correctement).

Cependant, je pense qu'une meilleure approche qu'un homologue inviter est pour les deux homologues à inviter mais qu'un seul homologue à accepter . J'utilise cette méthode maintenant et cela fonctionne très bien, car les deux pairs ont la possibilité de transmettre des informations riches à l'autre via le paramètre context de l'invitation, au lieu de devoir s'appuyer sur peu d'informations disponibles dans la méthode déléguée foundPeer.

Par conséquent, je recommande une solution comme celle-ci:

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

J'ai le même problème lorsque des périphériques tentent de se connecter simultanément et je ne sais pas comment trouver une raison, car nous n'avons aucune erreur avec MCSessionStateNotConnected .

Nous pouvons utiliser un moyen astucieux pour résoudre ce problème: Mettre dans les enregistrements txt (informations de découverte) une heure [[NSDate date] timeIntervalSince1970] lorsque l'application a démarré. Qui a commencé en premier - envoyez une invitation à d'autres.

Mais je pense que ce n'est pas une bonne façon (si les applications démarrent en même temps, peu probable ... :)). Nous devons trouver la raison.

3
Max Sokolov

Ceci est le résultat d'un bug que j'ai signalé à Apple. J'ai expliqué comment résoudre ce problème dans ma réponse à une autre question: Pourquoi mon homologue MCSession se déconnecte-t-il au hasard?

Je n'ai pas signalé la fusion de ces questions car, bien que le bogue sous-jacent et la solution soient les mêmes, les deux questions décrivent des problèmes différents.

2
Andrew Cone

Enregistrez le hachage de l'homologue B. À l'aide d'une minuterie, vérifiez en permanence l'état de la connexion si ce n'est pas le cas, essayez de vous reconnecter à chaque période donnée.

1
artud2000

Selon le document Apple Choix d'un invitant lors de l'utilisation de la connectivité Multipeer "Dans iOS 7, l'envoi simultané d'invitations peut faire échouer les deux invitations, les empêchant ainsi de communiquer entre elles."

Mais iOS 8 l'a corrigé.

0
Qiulang