I\'ve been struggling with an HTTP timeout issue recently. After more than one month of investigation I\'m quite sure that it is caused by bad HTTP persistent connections. Detai
Same issue here, iOS just try to reuse the connection after server drops it.
About two years ago, I switched to CFNetwork to workaround this issue, but recently I found it's not possible to implement SSL pinning with CFNetwork API. So now I'm considering go back to NSURLSession.
After some dig around, I found system will NOT reuse connections across NSURLSession
s, so creating new sessions within period of time, should solve the issue.
But I also found (at least on macOS): each connection made by NSURLSession can persistence last by 180 seconds, and that connection didn't close by release or reset the session, so you may need to implement some caching mechanism to avoid creating a lots of connections at the same time.
Here is the simple mechanism I'm currently use:
@interface HTTPSession : NSObject
@property (nonatomic, strong) NSURLSession * urlSession;
@property (nonatomic, assign) CFTimeInterval flushTime;
@end
+ (NSURLSession *)reuseOrCreateSession
{
static NSMutableArray * sessions = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sessions = [NSMutableArray array];
});
const CFTimeInterval serverTimeoutSeconds = 10;
const CFTimeInterval systemTimeoutSeconds = 40;
CFTimeInterval now = CFAbsoluteTimeGetCurrent();
HTTPSession * resultSession = nil;
for (HTTPSession * session in sessions) {
CFTimeInterval lifeTime = now - session.flushTime;
if (lifeTime < serverTimeoutSeconds) {
resultSession = session;
break;
}
if (lifeTime > systemTimeoutSeconds) {
resultSession = session;
resultSession.flushTime = now;
break;
}
}
if (!resultSession) {
resultSession = [HTTPSession new];
NSURLSession * session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
// setup session
resultSession.urlSession = session;
resultSession.flushTime = now;
[sessions addObject:resultSession];
}
return resultSession.urlSession;
}