NSNetServiceBrowser didRemoveService takes longer after opening stream
Asked Answered
A

2

7

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

Allemande answered 23/8, 2011 at 13:38 Comment(3)
As soon as I close the streams, didRemoveService fires. It seems to be waiting for some kind of timeout?Allemande
I am not sure if this is the case, but take a look at your -(void)stream:(NSStream*)aStream handleEvent:(NSStreamEvent)event handler. In Lion the handler is not called for the NSStreamEventEndEncountered event any more. So, you need to close your input stream and remove it from loop when you sure you have received all the data. For example when NSStreamEventHasBytesAvailable happens.Deandreadeane
For those with access to the Apple Developer forum. I've posted my problem here: devforums.apple.com/message/541436. Unfortunately still no solution :(Allemande
A
0

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.

Allemande answered 1/8, 2012 at 2:29 Comment(0)
M
0

I am sure its In Lion the handler is not called for the NSStreamEventEndEncountered event any more. So, you need to close your input stream and remove it from loop when you sure you have received all the data. For example when NSStreamEventHasBytesAvailable happens. Check it out and i guess it should work

Martens answered 1/12, 2011 at 12:47 Comment(1)
Unfortunately I have to keep my input streams open for device updates (printer out of paper, tray open etc etc). This problem occurs on Snow Leopard, iOS, Lion doesn't really matter.Allemande
A
0

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.

Allemande answered 1/8, 2012 at 2:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.