2009-07-31 11 views
5

Estoy tratando de escribir una aplicación que intercambie datos con otros iPhones que ejecuten la aplicación a través del marco de Game Kit. Los iPhones se descubren entre sí y se conectan bien, pero los problemas ocurren cuando envío los datos. Sé que los iPhones están conectados correctamente porque cuando serializo un NSString y lo envío a través de la conexión, sale bien en el otro extremo. Pero cuando intento archivar un objeto más grande (usando NSKeyedArchiver) aparece el mensaje de error "AGPSessionBroadcast failed (801c0001)".iPhone: envío de datos de gran tamaño con Game Kit

Supongo que esto se debe a que los datos que envío son demasiado grandes (mis archivos tienen un tamaño aproximado de 500k, Apple parece recomendar un máximo de 95k). He intentado dividir los datos en varias transferencias, pero nunca puedo deshacer el desarchivo correctamente en el otro extremo. Me pregunto si alguien más se ha enfrentado a este problema y cómo lo resolvió.

Respuesta

4

Tuve el mismo problema con los archivos alrededor de 300K. El problema es que el remitente necesita saber cuándo el receptor ha vaciado la tubería antes de enviar el siguiente fragmento.

Terminé con un motor de estado simple que funcionaba en ambos lados. El remitente transmite un encabezado con la cantidad de bytes totales que se enviarán y el tamaño del paquete, luego espera el reconocimiento desde el otro lado. Una vez que recibe el apretón de manos, procede a enviar paquetes de tamaño fijo, cada uno sellado con un número de secuencia.

El receptor recibe cada uno, lo lee y lo agrega a un búfer, luego escribe de vuelta a la tubería que obtuvo el paquete con la secuencia #. El remitente lee el paquete #, reduce el valor de otro búfer, y así sucesivamente. Cada lado realiza un seguimiento del estado en el que se encuentra (inactivo, enviando encabezado, recibiendo encabezado, enviando datos, recibiendo datos, error, hecho, etc.). Las dos partes deben hacer un seguimiento de cuándo leer/escribir el último fragmento, ya que es probablemente sea más pequeño que el tamaño completo del búfer.

Esto funciona bien (aunque un poco lento) y puede escalar a cualquier tamaño. Empecé con tamaños de paquete de 5K, pero funcionó bastante lento. Lo llevé a 10K, pero comenzó a causar problemas, así que retrocedí y lo sostuve en 8096. Funciona bien para datos binarios y de texto.

+0

Hola, Ramin, puedes compartir un fragmento de código relacionado con la solución que sugeriste. – Anshul

3

Tenga en cuenta que el GameKit no es una API general de transferencia de archivos; está destinado más a las actualizaciones de dónde está el jugador, cuál es la ubicación actual u otros objetos, etc. Por lo tanto, enviar 300k para un juego no parece sensato, aunque puedo entender el secuestro de la API para los mecanismos generales de intercambio.

El problema es que no es una conexión TCP; es más una conexión UDP (datagrama). En estos casos, los datos no son una secuencia (que se empaqueta con TCP), sino más bien una gran cantidad de datos. (Técnicamente, UDP puede fragmentarse en múltiples paquetes IP, pero pierde uno de ellos, y se pierde todo el UDP, en oposición a TCP, que volverá a intentar).

La MTU para la mayoría de las redes cableadas es ~ 1.5k; para bluetooth, es alrededor de ~ 0.5k. Entonces, cualquier paquete UDP que envíe (a) puede perderse, (b) puede dividirse en múltiples paquetes IP de tamaño MTU, y (c) si se pierde uno de esos paquetes, automáticamente perderá todo el conjunto.

Su mejor estrategia es emular TCP: envía paquetes con un número de secuencia. El extremo receptor puede solicitar transmisiones dupe de paquetes que luego desaparecieron. Si está utilizando el equivalente de un NSKeyedArchiver, una sugerencia es repetir las claves y escribirlas como claves individuales (suponiendo que cada valor con clave no es tan grande en sí mismo). Necesitará tener algún tipo de ACK por cada paquete que se envíe de regreso, y un ACK total cuando haya terminado, para que el remitente sepa que está bien soltar los datos de la memoria.

Cuestiones relacionadas