IOS 网络编程 + 后台保持连接

原文链接:http://blog.csdn.net/zj510/article/details/8935683

昨天在os x上写了个网络通信的小程序http://blog.csdn.net/zj510/article/details/8934312,今天在iphone也试了一下。

使用了Cocoa中的NSStream.代码相当的简单。

[cpp]  view plain copy
  1. - (void)Work_Thread:(NSURL *)url  
  2. {  
  3.     NSString* strHost = [url host];  
  4.     int port = [[url port] integerValue];  
  5.       
  6.     [NSStream getStreamsToHostNamed:strHost port: port inputStream:&readStream outputStream:&writeStream];  
  7.       
  8.     [readStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType];  
  9.     [readStream setDelegate:self];  
  10.     [readStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];  
  11.     [readStream open];  
  12.     NSLog(@"VOIP stream, %x", readStream);  
  13.       
  14.     [writeStream open];  
  15.     [writeStream write:"abcd" maxLength:4];  
  16.       
  17.   
  18.     NSInputStream* iStream;  
  19.     [NSStream getStreamsToHostNamed:strHost port:port inputStream:&iStream outputStream:nil];  
  20.     [iStream setDelegate: self];  
  21.     [iStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];  
  22.     [iStream open];  
  23.     NSLog(@"normal stream: %x", iStream);  
  24.   
  25.     [[NSRunLoop currentRunLoop] run];  
  26.   
  27. }  
这是个线程函数,里面创建了2个socket连接,并且关联到当前线程的run-loop。

为了接收NSStream的事件,需要实现NSStreamDelegate,如

[cpp]  view plain copy
  1. @interface KMasterViewController : UITableViewController <NSStreamDelegate>  

[cpp]  view plain copy
  1. - (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode  
  2. {  
  3.     NSLog(@" >> NSStreamDelegate in Thread %@", [NSThread currentThread]);  
  4.       
  5.     switch (eventCode) {  
  6.         case NSStreamEventHasBytesAvailable: {  
  7.               
  8.               
  9.             uint8_t buf[100] = {0};  
  10.             int numBytesRead = [(NSInputStream *)stream read:buf maxLength:100];  
  11.               
  12.             NSString* str = [NSString stringWithFormat:@"recv: %s", buf];  
  13.               
  14.             UILocalNotification* n = [[[UILocalNotification alloc] init] autorelease];  
  15.             [n setAlertBody:[NSString stringWithFormat:@"notify: %x", stream]];  
  16.             [[UIApplication sharedApplication] presentLocalNotificationNow:n];  
  17.             break;  
  18.         }  
  19.               
  20.         case NSStreamEventErrorOccurred: {  
  21.               
  22.             break;  
  23.         }  
  24.               
  25.         case NSStreamEventEndEncountered: {  
  26.               
  27.               
  28.             break;  
  29.         }  
  30.               
  31.         default:  
  32.             break;  
  33.     }  
  34. }  
收到数据后,显示一条notification。

就这么简单,使用http://blog.csdn.net/zj510/article/details/8934312里面的server,打开iphone程序,就可以收数据了。


但是这里有一个问题,iphone程序切到后台后,socket连接会断掉,ios的设计就是这样,

好在apple公司也没有那么绝,还是有一些东西可以在后台运行的,比如:

1. 音乐

2. gps

3. voip

这里我们可以将NSStream指定voip的属性,从而可以避免程序切到后台的时候socket连接中断。

步骤如下:

1. 在info.plist文件中,增加voip选项,如


2. 设置NSStream的属性,如

[cpp]  view plain copy
  1. [readStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType];  

这样,当程序切到后台的时候,这个socket连接还会被保持。上面的示例代码里面有2个连接,一个采用了voip属性,另外一个没有。

这样的话,当这个程序切到后台后,只有voip属性的那个socket还有效,另外一个将会失效。我测试了一下,确实是这样的。


另外,iphone都是通过wifi或者gprs上网的,那么当socket连接空闲一段时间后,这个连接有可能被路由器关闭,为了保持连接,我们需要不停发送心跳包。


由于iphone上的程序切到后台后,程序会被挂起,那么也就无法定时发送心跳包,所以这个问题只能由服务端来解决。普通的办法就是服务器每隔一定时间给每个客户端发送一个心跳包,以维持这个连接。每当客户端接收到心跳包的时候,客户端会被IOS唤醒,获得一小段CPU时间,然后再次进入挂起状态。

相关测试代码:http://download.csdn.net/detail/zj510/5390813


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值