2009-07-31 7 views
5

Ich versuche, eine App zu schreiben, die Daten mit anderen iPhones austauscht, die die App über das Game Kit-Framework ausführen. Die iPhones entdecken sich gegenseitig und verbinden sich gut, aber die Probleme treten auf, wenn ich die Daten sende. Ich weiß, dass die iPhones richtig verbunden sind, denn wenn ich einen NSString serialisiere und ihn über die Verbindung sende, kommt es am anderen Ende gut raus. Aber wenn ich versuche, ein größeres Objekt zu archivieren (mit NSKeyedArchiver) bekomme ich die Fehlermeldung "AGPSessionBroadcast failed (801c0001)".iPhone: Senden großer Daten mit Game Kit

Ich nehme an, dies liegt daran, dass die Daten, die ich sende, zu groß ist (meine Dateien sind etwa 500k groß, Apple scheint ein Maximum von 95k zu empfehlen). Ich habe versucht, die Daten in mehrere Übertragungen aufzuteilen, aber ich kann niemals erreichen, dass sie am anderen Ende richtig entpackt wird. Ich frage mich, ob jemand anderes auf dieses Problem gestoßen ist und wie Sie es gelöst haben.

Antwort

4

Ich hatte das gleiche Problem mit Dateien um 300K. Das Problem ist, dass der Sender wissen muss, wann der Empfänger die Pipe geleert hat, bevor er den nächsten Brocken sendet.

Ich endete mit einer einfachen State-Engine, die auf beiden Seiten lief. Der Absender sendet einen Header mit der Anzahl der gesendeten Bytes und der Paketgröße und wartet dann auf die Bestätigung von der anderen Seite. Sobald es den Handshake erhält, sendet es Pakete mit fester Größe, die jeweils mit einer Sequenznummer versehen sind.

Der Empfänger bekommt jedes, liest es und hängt es an einen Puffer an, schreibt dann zurück zum Rohr, dass es Paket mit der Reihenfolge # bekommen hat. Absender liest das Paket #, schneidet den Wert eines anderen Puffers aus und so weiter und so fort. Jede Seite verfolgt den Zustand, in dem sie sich befinden (Leerlauf, Header senden, Header empfangen, Daten senden, Daten empfangen, Fehler usw.). Die beiden Seiten müssen verfolgen, wann das letzte Fragment gelesen/geschrieben werden soll wahrscheinlich kleiner als die volle Puffergröße.

Dies funktioniert gut (wenn auch ein bisschen langsam) und es kann auf jede Größe skalieren. Ich begann mit 5K Paketgrößen, aber es lief ziemlich langsam. Ich habe es auf 10K geschoben, aber es hat Probleme verursacht, also habe ich es zurückgesetzt und habe es bei 8096 gehalten. Es funktioniert sowohl für Binär- als auch für Textdaten.

+0

Hallo Ramin, können Sie ein Code-Snippet mit der von Ihnen vorgeschlagenen Lösung teilen. – Anshul

3

Denken Sie daran, dass das GameKit keine allgemeine File-Transfer-API ist; es ist mehr für Updates von wo der Spieler ist, was der aktuelle Standort oder andere Objekte usw. sind. So scheint das Senden von 300k für ein Spiel nicht so sinnvoll, obwohl ich verstehen kann, die API für allgemeine Freigabe Mechanismen Hijacking.

Das Problem ist, dass es keine TCP-Verbindung ist; es ist mehr eine UDP (Datagramm) Verbindung. In diesen Fällen handelt es sich bei den Daten nicht um einen Stream (der von TCP paketiert wird), sondern um einen riesigen Datenblock. (Technisch kann UDP in mehrere IP-Pakete fragmentiert werden - aber eine davon verlieren, und das gesamte UDP ist verloren, im Gegensatz zu TCP, das es erneut versuchen wird).

Die MTU für die meisten verkabelten Netzwerke ist ~ 1.5k; für Bluetooth ist es um ~ 0.5k. Daher kann jedes UDP-Paket, das Sie (a) gesendet haben, verloren gehen, (b) in mehrere MTU-große IP-Pakete aufgeteilt werden, und (c) wenn eines dieser Pakete verloren geht, verlieren Sie automatisch den gesamten Satz.

Ihre beste Strategie ist TCP zu emulieren - es sendet Pakete mit einer Sequenznummer. Das empfangende Ende kann dann Dupe-Übertragungen von Paketen anfordern, die danach fehlten. Wenn Sie das Äquivalent eines NSKeyedArchiver verwenden, besteht ein Vorschlag darin, die Schlüssel zu durchlaufen und diese als einzelne Schlüssel auszugeben (vorausgesetzt, dass jeder Schlüsselwert nicht so groß ist). Sie müssen eine Art ACK für jedes zurückgesendete Paket und eine vollständige ACK haben, wenn Sie fertig sind, damit der Absender weiß, dass es OK ist, die Daten aus dem Speicher zu löschen.

Verwandte Themen