Почему NSNetServiceBrowser находит неопубликованные сервисы в iPhone OS?

Создание настольной версии моего мобильного приложения и обеспечение синхронизации пользователей по Wi-Fi. Все отлично работает в симуляторе - нет проблем с разрешением сетевых сервисов (которые публикуются настольным приложением) или замечанием, когда сервисы становятся недоступными.

Проблема заключается в том, что когда я запускаю приложение на телефонных службах, они обнаруживаются и разрешаются (иногда), но NSNetServiceBrowser никогда не замечает, когда служба становится недоступной. Когда это происходит, браузер сетевых служб постоянно находит сетевой сервис (который больше не публикуется), разрешает его, но затем не может подключиться к нему. После нескольких неудачных попыток сервисный браузер делегата "didRemoveService" наконец вызывается, и приложение снова начинает работать правильно.

Я бы опубликовал свой код, но обнаружил, что та же проблема возникает в примере Apple WiTap. Службы публикуются и обнаруживаются, но как только они становятся недоступными, клиент, на котором запущен браузер службы, не обновляется - и неоднократно пытается разрешить службу, которая "не должна" существовать.

Я обнаружил, что при запуске WiTap с выключенным wifi (так что Bonjour использует bluetooth) все работает отлично. Я не могу найти никого, жалующегося на то, что WiTap не работает, и не могу найти эту проблему где-либо еще в Интернете. Любая причина - возможно, с iPhone OS или моей беспроводной сетью - почему браузер сетевых служб может найти и правильно разрешить (но не может подключиться) службы, которые недоступны?

1 ответ

Bonjour/NSNetServiceBrowser на iPhone/iPod Touch будет использовать Wi-Fi и Bluetooth для обнаружения услуг - по крайней мере, на поддерживаемых устройствах. Каждый раз, когда вы начинаете просматривать сервисы, он выполняет поиск как по WiFi, так и по Bluetooth (это можно проверить в консоли iPhone в Организаторе). Поскольку ваше "устройство" симулятора не может использовать Bluetooth, ваш iPhone обнаруживает его через WiFi. Однако, если вы используете NSNetService для публикации на вашем iPhone, то вы также публикуете и по WiFi, и по Bluetooth (если поддерживается и включен). NSNetServiceBrowser, при работе на оборудовании с поддержкой BT, послушно обнаружит, что оба экземпляра, и сообщит об обоих через обратные вызовы делегата.

Настройка Bluetooth PAN занимает больше времени, чем публикация через Wifi, поэтому службы, обнаруженные в BT, часто хорошо отображаются после обнаружения и разрешения всех служб, основанных на Wi-Fi. При тестировании двух реальных устройств я даже видел, как обе службы отображаются в моем пользовательском интерфейсе (обычно только после сбоя другого телефона).

Это делает для некоторого расстраивающего кодирования, все же. Лучше всего использовать netService:didNotResolve: либо (i) повторить попытку разрешения, либо (ii) сделать недействительным экземпляр netService и подождать, пока другой телефон перезапустит свое приложение.

Кроме того, есть несколько других проблем, которые могут пойти не так. Поскольку предоставленный вам экземпляр NSNetService автоматически выпущен, вам необходимо сохранить его. Большинство людей добавляют его в NSMutableArray или NSMutableDictionary. Если это так, убедитесь, что вы правильно инициализировали его перед добавлением объекта. Так как сообщения на nil совершенно нормальны, если вы отправите addObject: на nil, все будет выглядеть так, как будто все работает нормально. За исключением того, что это не так. Это очень часто возникает при устранении неисправностей Bonjour, и происходит с лучшими из нас. Убедитесь, что ваш NSNetService запланирован в активно работающем цикле запуска, и тот, который работает в стандартном или обычном режимах.

Существует открытая ошибка, поданная в Apple (по состоянию на 10/4/09), в результате чего очень часто обновление Bonjour не приводит к запуску метода делегата. Я наблюдал это только на 3GS. В результате клиентское приложение не синхронизировано с сетью.

NSNetServiceBrowser должен постоянно уведомлять, когда служба покидает сеть (при номинальных условиях). Приведенная выше ошибка является только периодической и, по-видимому, специфичной для оборудования. Если вы видите, что это происходит последовательно, то, скорее всего, ваше приложение выдает исключение. Если вы используете фоновые потоки, это может произойти без сбоя всего приложения. Вы можете проверить консоль iPhone и журналы на наличие сообщений об ошибках. Убедитесь, что вы установили точку останова для символа objc_exception_throw.

Вот еще один совет по устранению неполадок, который я нашел бесценным. Наблюдайте за тем, как Bonjour вещает на вашем компьютере через терминал, используя следующую команду: dns-sd -B _serviceName. Это позволит вам увидеть все приходы и выходы в вашей локальной сети для вашего обслуживания. Если ваше приложение закрывается, но dns-sd не показывает событие Remove, то ваш код нуждается в пересмотре. Если dns-sd показывает событие удаления, но другие приложения не обрабатывают его правильно, возможно, вы видите вышеупомянутую ошибку. Может также случиться так, что ваш код не делает то, что вы думаете, он делает. И помните, это только поможет вам устранить неполадки сервиса Wi-Fi-to-Wifi Bonjour. Bluetooth для Bluetooth не поддерживается в симуляторе iPhone.

Прочитайте полную статью, Устранение неполадок Bonjour Networking для iPhone, в моем блоге разработчика.

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