Muy alta pérdida de packages UDP en iOs (GCDAsyncUdpSockets)

Estoy trabajando en una aplicación de iPhone para controlar el hardware físico.
La rutina es la siguiente:

  • la aplicación envía un datagtwig específico de "despertar" de 8 bytes en el canal de transmisión, en el puerto 8089; el post se envía repetidamente.
  • el hardware externo, que está escuchando el puerto 8089, recibe el post y envía un datagtwig de 94 bytes que contiene, entre otras cosas, la dirección IP y MAC del hardware; esto también está en el canal de transmisión.
  • la aplicación deja de enviar el post de "despertar", almacena IP y comienza a comunicarse con el hardware a través de un zócalo TCP

La rutina generalmente funciona. Sin embargo, a menudo recibo una pérdida inexplicable de packages UDP en la recepción; es decir, envío la señal de "despertar" de 8 bytes, pero no obtengo la respuesta de 94 bytes. Cuando la aplicación funciona, funciona perfectamente: casi no pierdo un solo package, y si la aplicación pierde el primer post de 94 bytes, obtiene el segundo o el tercero. Cuando no funciona, pierde todos los packages constantemente. La etapa "que no funciona" puede durar minutos u horas; No encontré ningún desencadenante aparente, es como si en algún momento, sin razón, la recepción deja de funcionar.

Antes de preguntar aquí, he hecho una debugging muy extensa. He supervisado los sockets a través de rvictl y tcpdump, y confirmé que mis loggings reflejan lo que sucede a nivel de socket. Para sacar el hardware externo de la ecuación, he creado una aplicación de espejo que se comporta como debería ser el hardware. He intentado cambiar los puertos, he intentado cerrar todos los nodos y restablecerlos, restablecerlos, pausar y reiniciar la recepción. Nada de esto funcionó.

He desarrollado mi biblioteca de comunicaciones con GCDAsyncUdpSocket. Para estar seguro, he experimentado también con la versión no GCD; El resultado es el mismo. Construí mi propia envoltura mínima alnetworkingedor de los zócalos de C; Tengo el mismo comportamiento.

Aquí está mi código de implementación:

GCDAsyncUdpSocket *udpSocket; - (void)startUdpBroadcast { if (udpSocket == nil) { // Setup our socket. udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; [udpSocket setIPv6Enabled:NO]; } NSLog(@"Listening for a message on %@",[self getBroadcastAddress]); NSError *bindError = nil; NSError *enableError = nil; NSError *receivingError = nil; [udpSocket bindToPort:8089 error:&bindError]; if (bindError) { NSLog(@"Error, can't bind: %@",[bindError localizedDescription]); return; } [udpSocket enableBroadcast:YES error:&enableError]; if (enableError) { NSLog(@"Error, can't enable broadcast: %@",[enableError localizedDescription]); return; } if (![udpSocket beginReceiving:&receivingError]) { NSLog(@"Error, can't receive: %@",[receivingError localizedDescription]); return; } [self logInfo:@"Start listening to UDP boradcast channel"]; [self sendUdpSignal]; repeatedBroadcastTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(sendUdpSignal) userInfo:nil repeats:YES]; } -(void)sendUdpSignal { NSData* signal = [self udpBroadcastSignal] ; NSLog(@"Send broadcast signal %@ on %@",signal, [self currentNetworkSsid]); [udpSocket sendData:signal toHost:[self getBroadcastAddress] port:8089 withTimeout:10 tag:0]; } 

¿Tienes alguna sugerencia?
¿Hay alguna forma de asegurarse de que la recepción de zócalos nunca se detenga?

Gracias por adelantado,
Davide