IOS 后台保持連接


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM