Очень высокая потеря пакетов UDP на iOs (GCDAsyncUdpSockets)

Я работаю над приложением для iPhone для управления физическим оборудованием.
Процедура выглядит следующим образом:

  • приложение отправляет определенную 8-байтовую дейтаграмму «пробуждения» по широковещательному каналу через порт 8089; сообщение отправляется повторно.
  • внешнее оборудование, прослушивающее порт 8089, получает сообщение и отправляет дейтаграмму размером 94 байта, содержащую, среди прочего, IP- и MAC-адрес оборудования; это также на канале вещания.
  • приложение перестает отправлять сообщение «пробуждение», сохраняет IP-адрес и начинает обмениваться данными с оборудованием через сокет TCP.

Процедура в целом работает. Однако я часто получаю необъяснимую потерю пакетов UDP при приеме; то есть я отправляю 8-байтовый сигнал «пробуждения», но не получаю 94-байтовый ответ. Когда приложение работает, оно работает идеально: я почти не теряю ни одного пакета, а если приложение пропускает первое 94-байтное сообщение, оно получает второе или третье. Когда он не работает, он постоянно пропускает все пакеты. Стадия «нерабочая» может длиться минуты или часы; Явного триггера не нашел - как будто на каком-то этапе без причины перестает работать прием.

Прежде чем спросить здесь, я сделал очень обширную отладку. Я отслеживал сокеты через rvictl и tcpdump и подтвердил, что мои журналы отражают то, что происходит на уровне сокетов. Чтобы исключить внешнее оборудование из уравнения, я создал зеркальное приложение, которое ведет себя так, как должно работать оборудование. Я пробовал менять порты, я пытался все время закрывать и обнулять сокеты, сбрасывать их, приостанавливать и перезапускать прием. Ничего из этого не сработало.

Я разработал свою коммуникационную библиотеку с помощью GCDAsyncUdpSocket. Чтобы быть в безопасности, я также экспериментировал с версией без GCD; результат тот же. Я создал свою собственную минимальную оболочку вокруг сокетов C; У меня такое же поведение.

Вот мой код реализации:

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];
}

Есть ли у вас какие-либо предложения?
Есть ли способ убедиться, что прием сокетов никогда не прекращается?

Заранее спасибо,
Давиде


person Davide    schedule 21.09.2014    source источник
comment
Вы нашли решение? У меня такая же проблема.   -  person Alan    schedule 28.11.2014
comment
Ответ здесь: stackoverflow.com/questions/13113435 /   -  person Sebas    schedule 18.08.2015