Брандмауэр Mac не позволяет корректно закрывать несколько UDP-портов многоадресной рассылки

На моем Mac OSX 10.74 я столкнулся с таким поведением, которое мне близко приближается к выводу, что это ошибка в программном обеспечении брандмауэра Mac OSX. Как правило, после выхода из приложения многоадресные UDP-порты, которые использовались во время сеанса, не были закрыты, кроме одного.

Для этой демонстрации я создал два приложения. Один называется UDPSender, он просто отправляет два сообщения двум группам многоадресной рассылки. Следующий фрагмент может быть запущен с Mac или с устройства iOS. GCDAsyncUdpSocket является последней версией.

GCDAsyncUdpSocket *udpSocket1;
GCDAsyncUdpSocket *udpSocket2;
udpSocket1 = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
udpSocket2 = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSData *data = [@"A test message from socket1" dataUsingEncoding:NSUTF8StringEncoding];
[udpSocket1 sendData:data toHost:@"239.1.1.110" port:46110 withTimeout:-1 tag:1];
data = [@"A test message from socket2" dataUsingEncoding:NSUTF8StringEncoding];
[udpSocket2 sendData:data toHost:@"239.1.1.120" port:46120 withTimeout:-1 tag:1];

Я создал другое приложение для Mac под названием UDPReceiver. (Это плохо себя ведет)

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
    GCDAsyncUdpSocket *udpSocket1;
    GCDAsyncUdpSocket *udpSocket2;
    udpSocket1 = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    udpSocket2 = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    NSError *error = nil;

    // udpSocket1
    if ([udpSocket1 bindToPort:46110 error:&error])
    {
        if (![udpSocket1 joinMulticastGroup:@"239.1.1.110" error:&error])
        {
            NSLog(@"udpSocket1 multicast failed to multicast group");
        }
        if (![udpSocket1 beginReceiving:&error])
        {
            [udpSocket1 close];
            NSLog(@"udpSocket1 rrror starting server (recv): %@", error);
        }
    } else  
    {
        NSLog(@"udpSocket1 rrror starting server (bind): %@", error);
        //        return;
    }

    // udpSocket2
    if ([udpSocket2 bindToPort:46120 error:&error])
    {
        if (![udpSocket2 joinMulticastGroup:@"239.1.1.120" error:&error])
        {
            NSLog(@"udpSocket2 multicast failed to multicast group");
        }
        if (![udpSocket2 beginReceiving:&error])
        {
            [udpSocket2 close];
            NSLog(@"udpSocket2 rrror starting server (recv): %@", error);
            return;
        }
    } else 
    {
        NSLog(@"udpSocket2 rrror starting server (bind): %@", error);
        //        return;
    }

}

- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
      fromAddress:(NSData *)address
withFilterContext:(id)filterContext
{
    NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"Receiving: %@", msg);
}

Последовательность тестов такая: с включенным брандмауэром Mac. Запустите UDPReceiver, запустите UDPSender. На компьютере UDPReceiver брандмауэр Mac запрашивает разрешение… выберите "Разрешить". Результатом являются два правильных лог-оператора:

2012-08-07 19:56:53.594 UDPReceiver[290:403] Receiving: A test message from socket1
2012-08-07 19:56:53.595 UDPReceiver[290:403] Receiving: A test message from socket2

Затем закройте UDPReceiver и снова откройте UDPReceiver. Сразу же вы увидите этот журнал.

2012-08-07 19:39:13.639 UDPReceiver[810:403] udpSocket1 rrror starting server (bind): Error Domain=NSPOSIXErrorDomain Code=48 "Address already in use" UserInfo=0x7fc7b3109d20 {NSLocalizedDescription=Address already in use, NSLocalizedFailureReason=Error in bind() function}

Если вы перезапустите UDPSender в этот момент, вы увидите другой вывод журнала:

2012-08-07 19:39:29.939 UDPReceiver[810:403] Receiving: A test message from socket2

Я открыл терминал Mac и использовал эту команду, чтобы увидеть активные порты: netstat -anf inet, Первая картинка была в первый раз, когда был выполнен UDPReceiver. Вторая картина была после того, как UDPReceiver был закрыт.

Я обнаружил, что есть два способа это исправить:

  1. Перезагрузите мой Mac. Тогда он снова будет работать правильно. Но вышеупомянутый симптом все еще сохраняется.
  2. Выключите брандмауэр полностью. Это полностью устранит проблему.

Кто-нибудь сталкивался с этим явлением раньше? Любое предложение, как (программирование) обойти это?

0 ответов

Другие вопросы по тегам