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

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

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

- (void)Work_Thread:(NSURL *)url
{
    NSString* strHost = [url host];
    int port = [[url port] integerValue];
    
    [NSStream getStreamsToHostNamed:strHost port: port inputStream:&readStream outputStream:&writeStream];
    
    [readStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType];
    [readStream setDelegate:self];
    [readStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [readStream open];
    NSLog(@"VOIP stream, %x", readStream);
    
    [writeStream open];
    [writeStream write:"abcd" maxLength:4];
    

    NSInputStream* iStream;
    [NSStream getStreamsToHostNamed:strHost port:port inputStream:&iStream outputStream:nil];
    [iStream setDelegate: self];
    [iStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [iStream open];
    NSLog(@"normal stream: %x", iStream);

    [[NSRunLoop currentRunLoop] run];

}
这是个线程函数,里面创建了2个socket连接,并且关联到当前线程的run-loop。

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

@interface KMasterViewController : UITableViewController 

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
    NSLog(@" >> NSStreamDelegate in Thread %@", [NSThread currentThread]);
    
    switch (eventCode) {
        case NSStreamEventHasBytesAvailable: {
            
            
            uint8_t buf[100] = {0};
            int numBytesRead = [(NSInputStream *)stream read:buf maxLength:100];
            
            NSString* str = [NSString stringWithFormat:@"recv: %s", buf];
            
            UILocalNotification* n = [[[UILocalNotification alloc] init] autorelease];
            [n setAlertBody:[NSString stringWithFormat:@"notify: %x", stream]];
            [[UIApplication sharedApplication] presentLocalNotificationNow:n];
            break;
        }
            
        case NSStreamEventErrorOccurred: {
            
            break;
        }
            
        case NSStreamEventEndEncountered: {
            
            
            break;
        }
            
        default:
            break;
    }
}
收到数据后,显示一条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选项,如

IOS 网络编程 + 后台保持连接_第1张图片

2. 设置NSStream的属性,如

[readStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType];

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

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

 

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

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

 

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


 




 

你可能感兴趣的:(网络编程)