1. 连接管理策略
- 持久连接:HTTP/2 本身支持持久连接,减少建立新连接的开销。在 Objective-C 中,使用
NSURLSession
进行网络请求时,默认支持持久连接。示例代码如下:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:@"https://example.com"];
NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 处理响应数据
}];
[task resume];
- 连接池:虽然
NSURLSession
已经对连接进行了一定程度的管理,但在复杂场景下,自定义连接池可以进一步优化。可以创建一个单例类来管理连接对象,例如:
@interface ConnectionPool : NSObject
@property (nonatomic, strong) NSMutableDictionary<NSURL *, NSURLSession *> *sessionPool;
+ (instancetype)sharedPool;
- (NSURLSession *)sessionForURL:(NSURL *)url;
@end
@implementation ConnectionPool
+ (instancetype)sharedPool {
static ConnectionPool *sharedPool = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedPool = [[ConnectionPool alloc] init];
sharedPool.sessionPool = [NSMutableDictionary dictionary];
});
return sharedPool;
}
- (NSURLSession *)sessionForURL:(NSURL *)url {
NSURLSession *session = self.sessionPool[url];
if (!session) {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
self.sessionPool[url] = session;
}
return session;
}
@end
2. 重传机制策略
- 自动重传:
NSURLSession
本身有一定的自动重传机制,但在复杂网络场景下可能不够。可以通过设置 NSURLSessionTask
的 retryCount
来增加重传次数。示例代码如下:
NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSInteger retryCount = 3;
if (task.currentRequest && task.currentRequest.retryCount < retryCount) {
// 重新发起请求
NSURLSessionDataTask *newTask = [session dataTaskWithURL:task.currentRequest.URL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 处理响应数据
}];
[newTask resume];
} else {
// 处理重传失败
}
}
}];
[task resume];
- 指数退避算法:在重传时采用指数退避算法,避免频繁重传导致网络拥塞。例如:
NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSInteger retryCount = task.currentRequest.retryCount;
NSTimeInterval delay = pow(2, retryCount) * 1; // 每次重传延迟翻倍
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSURLSessionDataTask *newTask = [session dataTaskWithURL:task.currentRequest.URL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 处理响应数据
}];
[newTask resume];
});
}
}];
[task resume];
3. 错误处理策略
- 网络错误处理:在
NSURLSession
的代理方法中处理网络错误,例如:
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
if (error) {
// 根据错误码进行不同处理
switch (error.code) {
case NSURLErrorTimedOut:
// 处理超时错误
break;
case NSURLErrorNotConnectedToInternet:
// 处理无网络连接错误
break;
default:
// 处理其他错误
break;
}
} else {
// 处理成功响应
}
}
- 数据校验与修复:在接收到数据后,对数据进行校验,如使用哈希校验。如果数据有误,请求重新传输。示例代码如下:
NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error && data) {
NSString *expectedHash = @"expected_hash_value";
NSString *actualHash = [self calculateHashForData:data];
if (![expectedHash isEqualToString:actualHash]) {
// 数据校验失败,重新请求
NSURLSessionDataTask *newTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 处理响应数据
}];
[newTask resume];
} else {
// 数据校验成功,处理数据
}
}
}];
[task resume];
- (NSString *)calculateHashForData:(NSData *)data {
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(data.bytes, (CC_LONG)data.length, digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]];
return output;
}
4. 网络切换处理策略
- 监听网络状态:使用
Reachability
库监听网络状态变化。在网络切换时,暂停当前请求,重新评估网络状况后决定是否重新发起请求。示例代码如下:
#import "Reachability.h"
@interface ViewController ()
@property (nonatomic, strong) Reachability *reachability;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.reachability = [Reachability reachabilityForInternetConnection];
[self.reachability startNotifier];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil];
}
- (void)reachabilityChanged:(NSNotification *)note {
Reachability *reachability = note.object;
NetworkStatus status = [reachability currentReachabilityStatus];
if (status == NotReachable) {
// 暂停所有网络请求
for (NSURLSessionTask *task in self.session.tasks) {
[task suspend];
}
} else if (status == ReachableViaWiFi || status == ReachableViaWWAN) {
// 重新评估网络状况,决定是否重新发起请求
for (NSURLSessionTask *task in self.session.tasks) {
if (task.state == NSURLSessionTaskStateSuspended) {
[task resume];
}
}
}
}
@end