it-swarm.com.de

Verbindung zu nicht verbundenen Peers wiederherstellen

Ich verwende das iOS 7 Multipeer-Framework in meiner App, habe jedoch ein Problem mit der Trennung der Geräte. Wenn ich die App in zwei Geräten öffne: Gerät A und Gerät B, verbinden sich die beiden Geräte automatisch miteinander. Nach einigen Sekunden trennt sich Gerät A jedoch von Gerät B. Das heißt, die Verbindung sieht zunächst folgendermaßen aus:

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

Nach einigen Sekunden:

A ---> B
A      B

Gerät A behält seine Verbindung bei, Gerät B erhält jedoch einen MCSessionStateNotConnected. 

Dies bedeutet, dass A Daten an B senden kann, B jedoch nicht antwortet. Ich habe versucht, dies zu umgehen, indem ich prüfe, ob das Gerät angeschlossen ist, und wenn nicht, die Verbindung erneut herstellt, indem Sie Folgendes verwenden:

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

Aber der didChangeState Callback wird einfach mit MCSessionStateNotConnected aufgerufen. 

Seltsamerweise schicke ich App A in den Hintergrund und öffne sie erneut. B verbindet sich erneut mit der App und die Verbindung bleibt erhalten. 

Die Multipeer-API (und Dokumentation) scheint etwas spärlich zu sein, daher ging ich davon aus, dass sie einfach funktionieren würde. Wie soll ich das Gerät in dieser Situation wieder anschließen?

30
Ben Smiley

Ich hatte das gleiche Problem, und es scheint, dass meine App gleichzeitig durchsucht und Werbung geschaltet wurde und zwei Einladungen gesendet/akzeptiert wurden. Als ich damit aufhörte und einen Peer auf den anderen für Einladungen verschieben ließ, blieben die Geräte verbunden.

In meinem Browser-Delegierten überprüfe ich den Hashwert der erkannten displayName-Gegenstelle und sende nur dann eine Einladung, wenn mein Gegenüber einen höheren Hashwert hat:

Bearbeiten

Wie von @Masa dargelegt, unterscheidet sich der hash-Wert einer NSString auf 32- und 64-Bit-Geräten. Daher ist es sicherer, die compare:-Methode für displayName zu verwenden. 

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

Wie Sie sagen, die Dokumentation ist spärlich. Wer weiß also, was Apple wirklich von uns erwartet, aber ich habe mit dem Senden und Akzeptieren von Einladungen in einer einzigen Sitzung experimentiert und außerdem eine neue Sitzung für jede angenommene/gesendete Einladung erstellt, dies jedoch bestimmte Art, Dinge zu tun, hat mir den größten Erfolg gebracht. 

22
ChrisH

Für alle Interessierten habe ich MCSessionP2P erstellt, eine Demo-App, die die Ad-hoc-Netzwerkfunktionen von MCSession veranschaulicht. Die App kündigt sich selbst im lokalen Netzwerk an und stellt programmatisch eine Verbindung zu verfügbaren Peers her, um ein Peer-to-Peer-Netzwerk aufzubauen. Hat einen Tipp an @ChrisH für seine Technik des Vergleichens von Hashwerten für das Einladen von Kollegen.

5
Marco

Ich mochte die Lösung von ChrisH, die die wichtigsten Erkenntnisse offenbart, dass nur ein Peer sollte sich mit dem anderen Peer verbinden , nicht beides. Gegenseitige Verbindungsversuche führen zu gegenseitiger Trennung (obgleich nicht, dass eine einseitige Verbindung tatsächlich ist ist, kontra-intuitiv eine wechselseitige Verbindung in Bezug auf Status und Kommunikation, sodass das problemlos funktioniert).

Ich denke jedoch, dass ein besserer Ansatz als ein Peer Inviting für beide Peers gilt, aber nur einen Peer zu Accept . Ich verwende diese Methode jetzt und sie funktioniert hervorragend, da beide Peers die Möglichkeit haben, über den Parameter context der Einladung reiche Informationen an den anderen Benutzer zu übergeben, statt sich auf wenige Informationen zu verlassen, die in der Delegate-Methode foundPeer verfügbar sind.

Daher empfehle ich eine Lösung wie folgt:

- (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

Ich habe das gleiche Problem, wenn Geräte versuchen, sich gleichzeitig miteinander zu verbinden, und ich weiß nicht, wie ich einen Grund finden kann, weil wir mit MCSessionStateNotConnected keine Fehler haben.

Wir können eine raffinierte Methode verwenden, um dieses Problem zu lösen: In txt-Datensätzen (Discovery-Informationen) eine Uhrzeit eingeben [[NSDate-Datum] timeIntervalSince1970] , wenn die App gestartet wird. Wer zuerst angefangen hat - schicke eine Einladung an andere.

Aber ich denke, es ist kein richtiger Weg (wenn Apps gleichzeitig starten, unwahrscheinlich ... :)). Wir müssen den Grund herausfinden.

3
Max Sokolov

Dies ist das Ergebnis eines Fehlers, den ich an Apple gemeldet habe. In meiner Antwort auf eine andere Frage habe ich erklärt, wie Sie das Problem beheben können: Warum trennt sich mein MCSession-Peer zufällig?

Ich habe diese Fragen nicht für das Zusammenführen markiert, da der zugrunde liegende Fehler und die Lösung gleich sind, die beiden Fragen jedoch unterschiedliche Probleme beschreiben.

2
Andrew Cone

Speichern Sie den Hash des Peers B. Überprüfen Sie mithilfe eines Timers den Status der Verbindung fortlaufend, wenn keine Verbindung besteht. Versuchen Sie, die Verbindung mit dem jeweils angegebenen Zeitraum erneut herzustellen.

1
artud2000

Laut Apple-Dokument Auswahl eines Einladers bei der Verwendung von Multipeer-Konnektivität “Beim Senden von gleichzeitigen Einladungen unter iOS 7 können beide Einladungen fehlschlagen, sodass beide Partner nicht miteinander kommunizieren können.“

Aber iOS 8 hat es behoben.

0
Qiulang