I have the following code for discovering services on the network:
[netServiceBrowser setDelegate: self];
[netServiceBrowser searchForServicesOfType: serviceType inDomain: domain];
That results in calls to these two methods (find service and remove service):
- (void) netServiceBrowser:(NSNetServiceBrowser*) netServiceBrowser
didFindService:(NSNetService*) netService ... {}
- (void) netServiceBrowser:(NSNetServiceBrowser*) netServiceBrowser
didRemoveService:(NSNetService*) netService ... {}
This works fine. When I turn off my device I immediately receive the didRemoveService call.
However when I open a stream (input, output or both) to the device:
[netService getInputStream: &inputStream outputStream: &outputStream];
[inputStream setDelegate: self];
[outputStream setDelegate: self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode: NSDefaultRunLoopMode];
[inputStream open];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[outputStream open];
It suddenly takes the NSNetServiceBrowser almost a minute to detect that I turned off the device
(it takes a minute for didRemoveService to be called).
Devices that I'm not communicating with (opening streams with) still call didRemoveService as soon as I remove them.
Update: Here is a bit more information related to my problem.
I've ran a trace with Wireshark and noticed the following:
I start my application in the iPad simulator, the application starts a NSNetServiceBrowser and detects the printer. After that it opens the input/output streams to the device (via airport express, usb). The printer is sending me status updates and when I tap the test button in my app the printer starts printing. In Wireshark I see all the communication with the printer as expected.
Now when I start the exact same application on the iPad (and leave the iPad simulator running). The application starts the NSNetServiceBrowser as well, and detects the printer. The printer is not sending me status updates and when I tap the test button, the printer is not printing. In Wireshark I see the communication. The printer or airport receives my commands and sends an ACK package.
As soon as I kill the iPad simulator app, the printer starts to print the commands that I've sent using the iPad. It seems that opening a socket blocks all bonjour events, how can I prevent this from happening?
More here: https://devforums.apple.com/message/541436
It seems to be a limitation of the Airport Express.
My current implementation with GCDAsyncSocket works pretty well and I just have to make sure that only one socket is used to communicate with the Airport Express.
I'm closing the question.