iPhone Socket неожиданно закрывается - PullRequest
0 голосов
/ 16 ноября 2010

Ну, по крайней мере, неожиданно для меня ... Это ситуация Я открываю сокет, используя следующий код:

 CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)ipaddress , 3333,&readStream, &writeStream);
 if(!CFReadStreamOpen(readStream) || !CFWriteStreamOpen(writeStream))
 {
  UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Connection error"
              message:@"There has been a connection error, please ensure your internet connection is working"
                delegate:self
             cancelButtonTitle:@"OK"
             otherButtonTitles:nil];

  [alert show];
  return;
 }

Все идет хорошо, следующее, что я делаю, это настраиваю обратный вызов:

    CFStreamClientContext ctxt = {0,(void*)NULL,NULL,NULL,NULL};
 static const CFOptionFlags kReadNetworkEvents = kCFStreamEventEndEncountered |
 kCFStreamEventErrorOccurred |
 kCFStreamEventHasBytesAvailable |
 kCFStreamEventOpenCompleted |
 kCFStreamEventNone;


 CFReadStreamSetClient(readStream, kReadNetworkEvents, ReadStreamClientCallBack, &ctxt);
 CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);

Также отлично работает, я перечислю метод обратного вызова для завершения:

    static void ReadStreamClientCallBack( CFReadStreamRef stream, CFStreamEventType type, void *clientCallBackInfo ) {
 switch (type)
 {
  case kCFStreamEventEndEncountered:
  {
   break;
  }
  case kCFStreamEventErrorOccurred:
   break;
  case kCFStreamEventHasBytesAvailable:
  {
   [this stopListen];
   UInt8 buffer[1024];
   int count = CFReadStreamRead(stream, buffer, 1024);
   CFStreamStatus status = CFReadStreamGetStatus(this.readStream);
   CFErrorRef error = CFReadStreamCopyError (this.readStream);
   CFStringRef errorCode = CFErrorCopyDescription(error);
  // Bunch of other irrelevant code

Теперь, что идет не так: весь этот код работает отлично, пока я остаюсь в приложении, даже если я выхожу из приложения и снова вхожу, он все еще работает нормально. Если я вхожу в режим ожидания, когда приложение открыто, оно также работает нормально. Однако, если я выйду из приложения, переведу телефон в режим ожидания, вытащу телефон из режима ожидания и снова войду в приложение, немедленно будет вызван обратный вызов с типом события kCFStreamEventHasBytesAvailable, хотя я уверен на 100%, что ни одного байта не было отправлено. Если я затем вызываю CFReadStreamRead, он возвращает мне -1, поскольку это означает, что произошла ошибка. Я выяснил код ошибки, равный 57, это означает, что сокет был закрыт.

Я пропускаю определенный аспект программирования сокетов на iPhone? Я должен признать, что я новичок в этом. Разве невозможно оставить TCP-сокет открытым, находясь вне приложения (и переходя в режим ожидания)? Я попытался снова вызвать CFReadStreamOpen, который вернул мне значение false.

Я здесь потерян, пожалуйста, помогите!

Заранее спасибо

1 Ответ

1 голос
/ 16 ноября 2010

Часть функций многозадачности в 4.0+ требует дополнительного кодирования для поддержки поддержки соединений и выполнения задач в фоновом режиме.Вы, вероятно, просто жертва ОС, забирающей эти ресурсы, так как вы не «подписались» на них в соответствующее время.

В этом разделе рассматриваются основы фонового доступа:

http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

В частности, это:

Будьте готовы обрабатывать сбои соединения в сетевых сокетах.Система может разорвать сокетные соединения, пока ваше приложение приостановлено по ряду причин.Пока ваш код на основе сокетов подготовлен для других типов сбоев сети, таких как потерянный сигнал или сетевой переход, это не должно приводить к каким-либо необычным проблемам.Когда ваше приложение возобновляет работу, если оно сталкивается с ошибкой при использовании сокета, просто восстановите соединение.

Однако есть три совершенно особые вещи, которые вы можете делать в фоновом режиме, и если вы делаете этодолжен объявить их в вашем Info.plist, чтобы быть хорошим гражданином приложения.Эти три значения находятся в свойстве UIBackgroundModes, и они audio location и voip

Вы можете запросить больше времени для своей задачи, зарегистрировав блок (даже если это не гарантирует васВы получите это) вот так:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    UIApplication*    app = [UIApplication sharedApplication];

    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];

    // Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Do the work associated with the task.

        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    });
}

См. также Краткое практическое руководство по блокам для быстрого обзора и Руководство по программированию параллелизма для получения более подробной информации.

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