iPhone Socket意外关闭

时间:2010-11-16 14:06:50

标签: iphone sockets callback

至少对我来说意外......这就是情况: 我使用以下代码打开一个Socket:

 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

现在出了什么问题:只要我留在应用程序中,所有这些代码都可以正常工作,即使我退出应用程序并再次输入它仍然可以正常工作。如果我在应用程序打开时进入待机状态,它也可以正常工作。但是,如果我退出应用程序,将我的手机置于待机状态,让手机退出待机状态并重新进入应用程序,即使我100%确定没有发送任何字节,也会立即调用回调,事件类型为kCFStreamEventHasBytesAvailable。如果我然后调用CFReadStreamRead它返回-1给我,因为这意味着发生错误我发现错误代码是57,这意味着套接字已经关闭。

我是否忽略了iPhone上套接字编程的某些方面?我必须承认我是新手。在退出应用程序(并进入待机状态)时是否无法打开TCP套接字? 我曾尝试再次调用CFReadStreamOpen,并向我返回false。

我迷路了,请帮忙!

提前致谢

1 个答案:

答案 0 :(得分:1)

4.0+中的部分多任务功能需要额外的编码来支持保持连接活动并在后台执行任务。您可能只是操作系统的受害者,因为您没有在适当的时候“选择加入”这些资源。

本节介绍了背景知识的基础知识:

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

特别是:

  

准备好处理连接   基于网络的故障   插座。系统可能会拆除   你的套接字连接   申请暂停任何   原因多少。只要你的   基于套接字的代码准备好了   其他类型的网络故障,例如   作为丢失的信号或网络   转型,这不应该导致   任何异常问题。当你的   应用程序恢复,如果它遇到   简单地说,使用套接字失败了   重建连接。

但是,您可以在后台执行三项非常特殊的事情,如果您这样做,则应在Info.plist中声明它们以成为优秀的应用程序公民。这三个值位于UIBackgroundModes属性中,它们是audio locationvoip

你可以通过注册一个块来请求更多的时间来完成你的任务(即使它不是你会得到它的保证),如下所示:

- (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;
    });
}

有关详细信息,请参阅A Short Practical Guide to BlocksConcurrency Programming Guide