当iphone应用程序进行网络编程时,切到后台后,socket连接会断掉,ios的设计就是这样。

但是好在apple公司也没有那么绝,还是有一些东西可以在后台运行的(backgroundmodes),

比如:音乐 GPS  Voip Locationupdates等

我们以voip为例

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

可以分为两步:

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

2. 设置NSStream的属性,如

在IOS中,sockets是用流或者更高级的结构,设置一个VOIP的socket,你只需要在通常的设置中添加一个特殊的key来标明这个接口是用于连接VOIP服务的,下表列出了流的接口和设置:

设置流接口用于voip接口

NSInputStream 和NSOutputStream 对于 Cocoa streams, 使用 setProperty:forKey: 方法添加

NSStreamNetworkServiceType 属性给 stream. 改属性的值设为 NSStreamNetworkServiceTypeVoIP.

[readStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType];

这样,当程序切到后台的时候,这个socket连接还会被保持。

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

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

解决方法:

通过设置以下属性可以保持socket连接和数据的继续传输

1.需要在Info.plist文件中添加UIBackgroundModes中的VOIP键值;

2.设置流属性

CFReadStreamRef和CFWriteStreamRef通过如下方法设置kCFStreamNetworkServiceType属性为kCFStreamNetworkServiceTypeVoIP;

CFReadStreamSetProperty(theReadStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);

CFWriteStreamSetProperty(theWriteStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);

NSInputStream 和NSOutputStream通过如下方法设置NSStreamNetworkServiceType属性为NSStreamNetworkServiceTypeVoIP;

[self.stream setProperty: NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType];

3.这里有一个问题,就是客户端是通过心跳来和服务端保持连接,心跳是由定时器触发的,当我退到后台以后,定时器方法被挂起,那么通过如下设置来在后台运行定时器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

- (
void)applicationDidEnterBackground:(UIApplication
*)application{
 

    
UIApplication*  
app = [UIApplication sharedApplication];

    
__block   
UIBackgroundTaskIdentifier bgTask;

    
bgTask
= [app beginBackgroundTaskWithExpirationHandler:^{

        
dispatch_async(dispatch_get_main_queue(),
^{

            
if

(bgTask != UIBackgroundTaskInvalid)

            
{

                
bgTask
= UIBackgroundTaskInvalid;

            
}

        
});

    
}];

    
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,

0
),
^{

        
dispatch_async(dispatch_get_main_queue(),
^{

            
if

(bgTask != UIBackgroundTaskInvalid)

            
{

                
bgTask
= UIBackgroundTaskInvalid;

            
}

        
});

    
});

}

最新文章

  1. Dictionary读取键值的快捷方法
  2. XE6 & IOS开发之开发者账号、苹果证书(1):关于开发者账号
  3. cometd使用-bayeux协议(读法:贝叶)
  4. Zero_qiqi DIV模式的省市区三级联动
  5. wxpython线程安全的方法
  6. uploadify控件使用在.net
  7. windows和linux下获取当前程序路径以及cpu数
  8. 【安德鲁斯】基于脚本的数据库"增量更新",如果不改变,每次更新java代码、!
  9. [CLR via C#]5.3 值类型的装箱和拆箱
  10. jdk下载以及配置
  11. Go语言Context(设计及分析)
  12. JVM服务进程挂掉问题定位查询思路
  13. python3 pickle模块
  14. Shell-14--awk
  15. VsCode插件开发之入门示例
  16. Java代码审计连载之—添油加醋
  17. 01: vue.js安装
  18. EBS FORM 编译
  19. Rico Board.1.环境配置
  20. Android NDK开发篇(五):Java与原生代码通信(数据操作)

热门文章

  1. BZOJ 5313: 新Fib数列
  2. HDU 3594 Cactus 有向仙人掌图判定
  3. HDU 3315 KM My Brute
  4. String的getBytes()方法
  5. python - 接口自动化测试实战 - case1 - 再次优化版
  6. MongoDB 3.6 安装详解
  7. api调用安全
  8. PAT 甲级 1003. Emergency (25)
  9. 【CF676C】Vasya and String(二分查找,线性扫描尺取法)
  10. 42深入理解C指针之---指针与队列