title: Mac Firewall prevents from closing multiple multicast UDP ports properly
body: <p>On my Mac OSX 10.74, I encountered this behavior that I am getting close to conclude it is a bug in the Mac OSX's Firewall software.  Basically, after an application quit, the multicast UDP ports that were used during the session were not closed except one.  </p>
  
  <p>For the purpose of this demonstration, I set up two applications.  One is called UDPSender, it just sends two messages to two multicast groups.  The following snippet can be run from a Mac or from an iOS device.  GCDAsyncUdpSocket is the latest version.</p>
  
  <pre><code>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];
  </code></pre>
  
  <p>I created another application for the Mac called UDPReceiver.  (This is the misbehaved one)</p>
  
  <pre><code>- (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:&amp;error])
      {
          if (![udpSocket1 joinMulticastGroup:@"239.1.1.110" error:&amp;error])
          {
              NSLog(@"udpSocket1 multicast failed to multicast group");
          }
          if (![udpSocket1 beginReceiving:&amp;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:&amp;error])
      {
          if (![udpSocket2 joinMulticastGroup:@"239.1.1.120" error:&amp;error])
          {
              NSLog(@"udpSocket2 multicast failed to multicast group");
          }
          if (![udpSocket2 beginReceiving:&amp;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);
  }
  </code></pre>
  
  <p>The test sequence like this:  With your Mac's Firewall on.  Start UDPReceiver, Start UDPSender.  On the UDPReceiver machine, Mac's Firewall prompts for permission… select allow.  The result is two correct logs statements:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Next, shutdown UDPReceiver, and re-open UDPReceiver again.  Immediately, you will see this log. </p>
  
  <pre><code>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}
  </code></pre>
  
  <p>If you restart UDPSender at this moment, you will see the other log output:</p>
  
  <pre><code>2012-08-07 19:39:29.939 UDPReceiver[810:403] Receiving: A test message from socket2
  </code></pre>
  
  <p>I opened the Mac Terminal and used this command to see the active ports:  <code>netstat -anf inet</code>.  The first picture was the first time UDPReceiver was executed.  The second picture was after UDPReceiver was closed.</p>
  
  <p>I found out there are two ways to fix this:  </p>
  
  <ol>
  <li>Restart my Mac.  Then it will work correctly again.  But the above symptom still persists. </li>
  <li>Turn off the firewall completely.  This will eliminate the issue completely.</li>
  </ol>
  
  <p>Has anyone encountered this phenomenon before?   Any suggestion how to (programming) work around this?</p>
  
  <p><img src="https://i.stack.imgur.com/Np9or.jpg" alt="enter image description here"></p>
  
  <p><img src="https://i.stack.imgur.com/GWI1u.jpg" alt="enter image description here"></p>