При отправке пакетов UDP на iPhone происходит сбой по новому новому соединению 3G, но работает иначе - PullRequest
5 голосов
/ 25 июля 2010

У меня странная проблема при отправке UDP-пакетов с iPhone через 3G. Практически каждый раз, когда мое приложение запускается после более длительного периода бездействия сети (например, после того, как телефон выходит из спящего режима или просто получает соединение 3G), мое приложение не может отправлять какие-либо пакеты UDP. Я получаю kCFSocketError статус ошибки от CFSocketSendData. Затем логика приложения повторяет попытку периодически отправлять пакет каждые пять секунд, но независимо от того, как долго я позволяю ему запускаться , он продолжает отказывать . Однако, когда я переключаю приложение в фоновый режим и открываю, например, веб-страницу в Safari (в то время как приложение все еще не работает в фоновом режиме), приложение внезапно начинает работать. По сути, похоже, что другие сетевые действия (из Safari, Maps и т. Д.) «Запускают сеть по-настоящему». Нужно ли делать что-то особенное, например, с точки зрения инициализации сети?

Это упрощенный фрагмент кода, который я использую для отправки пакетов UDP:

CFSocketRef cfSocket = CFSocketCreate(NULL, 0, SOCK_DGRAM, IPPROTO_UDP, kCFSocketNoCallBack, NULL, NULL);
if (!cfSocket)
{
    // snip: some error handling
}

struct sockaddr_in addr;
// snip: init addr

CFDataRef cfAddr = CFDataCreate(NULL, (unsigned char *)&addr, sizeof(addr));

CFSocketError sendPacketResult = CFSocketSendData(cfSocket, cfAddr, cfPacketData, 0.0);
if (sendPacketResult != kCFSocketSuccess)
{
    // try again in 5 seconds
}

Всё работает без проблем по Wi-Fi.

Честно говоря, я думаю, что иногда (но очень редко) я видел такое же поведение в стандартных приложениях для iPhone (Safari, Карты, ...). Иногда они отказываются подключаться (даже думал, что вижу значок 3G), и мне нужно закрыть и снова открыть их. Но это очень редко.

Редактировать: Возможный связанный вопрос: Что на iPhone значит EPERM (errno == 1) в ответ на send () данных UDP? .

1 Ответ

4 голосов
/ 19 января 2011

Сетевой интерфейс 3G TCP / IP может быть сорван IOS по усмотрению операционной системы, как правило, из соображений экономии энергии, если по ней не проходит трафик. При использовании сокетов BSD (например, для UDP, поскольку отсутствует сетевая структура Apple для UDP), не публикуется вызов ОС для проверки работоспособности сетевого интерфейса 3G. Но внутри класса Apple CFSocketStream существуют частные вызовы Apple, которые пробуждают интерфейс.

Таким образом, решение, похоже, заключается в том, чтобы открыть CFSocketStream в каком-либо месте. Это разбудит интерфейс на некоторое время. Пока вы отправляете данные через CFSocketStream раз в минуту, соединение и сетевой интерфейс будут работать.

Это не так уж привлекательно, так как работает только с побочным эффектом. Но, похоже, на данный момент это единственное решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...