工程中使用tcp長(zhǎng)連接來(lái)和服務(wù)端進(jìn)行數(shù)據(jù)傳輸,在IOS平臺(tái)上,由于蘋(píng)果的后臺(tái)機(jī)制,會(huì)有以下問(wèn)題:
當(dāng)程序退到后臺(tái)的時(shí)候,所有線(xiàn)程被掛起,系統(tǒng)會(huì)回收所有的socket資源,那么socket連接就會(huì)被關(guān)閉,因此無(wú)法再進(jìn)行數(shù)據(jù)的傳輸:
解決方法:
通過(guò)設(shè)置以下屬性可以保持socket連接和數(shù)據(jù)的繼續(xù)傳輸
1.需要在Info.plist文件中添加UIBackgroundModes中的VOIP鍵值;
2.設(shè)置流屬性
CFReadStreamRef和CFWriteStreamRef通過(guò)如下方法設(shè)置kCFStreamNetworkServiceType屬性為kCFStreamNetworkServiceTypeVoIP;
CFReadStreamSetProperty(theReadStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
CFWriteStreamSetProperty(theWriteStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
NSInputStream 和NSOutputStream通過(guò)如下方法設(shè)置NSStreamNetworkServiceType屬性為NSStreamNetworkServiceTypeVoIP;
[self.stream setProperty: NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType];
3.這里有一個(gè)問(wèn)題,就是客戶(hù)端是通過(guò)心跳來(lái)和服務(wù)端保持連接,心跳是由定時(shí)器觸發(fā)的,當(dāng)我退到后臺(tái)以后,定時(shí)器方法被掛起,那么通過(guò)如下設(shè)置來(lái)在后臺(tái)運(yùn)行定時(shí)器
- (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;
}
});
});
}