您的位置:首页 > 理论基础 > 计算机网络

从NSURLSession到AFNetworking再到自己封装一个网络框架

2017-11-17 12:31 453 查看

从NSURLSession讲起

首先从七层网络协议讲起:物理层 –> 数据链路层 –> 网络层 –> 传输层 –> 会话层 –> 表示层 –> 应用层,我们说的NSURLSession是会话层。

常用术语讲解:

NSURL:请求地址,定义一个网络资源路径。一个请求地址由协议、主机地址、路径、参数(非必须)构成。

NSURLRequest:网络请求,根据请求地址建立一个请求。

NSMutableURLRequest:可变网络请求,可以设置请求头等信息。

NSURLSessionTask经典图:

NSURLSessionDataTask用来处理一般的网络请求,它的子类NSURLSessionUploadTask用来处理上传网络请求,NSURLSessionDownloadTask用来处理下载的网络请求



Demo链接下载 密码: 66is

1.block解析返回GET数据

//请求路径
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//解析返回数据
}];
[dataTask resume];


2.block解析返回POST数据

//请求路径
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
NSMutableURLRequest *mulRequest = [[NSMutableURLRequest alloc] initWithURL:url];
//设置请求方法和请求体
mulRequest.HTTPMethod = @"POST";
mulRequest.HTTPBody = [@"username=zhaoliying&password=1314" dataUsingEncoding:NSUTF8StringEncoding];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:mulRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//解析返回数据
}];
[dataTask resume];


3.代理解析返回数据

- (void)postDelegateNetWork {
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
NSMutableURLRequest *mulRequest = [[NSMutableURLRequest alloc] initWithURL:url];
mulRequest.HTTPMethod = @"POST";
mulRequest.HTTPBody = [@"username=zhaoliying&password=1314" dataUsingEncoding:NSUTF8StringEncoding];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:mulRequest];
[dataTask resume];

}

#pragma NSURLSessionDelegate
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(nonnull NSURLResponse *)response completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler {
//接收到服务器响应的时候调用
completionHandler(NSURLSessionResponseAllow);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
//接收到服务器返回数据的时候调用
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
//解析服务器返回数据
}


4.下载文件

NSURL *url = [NSURL URLWithString:@"https://music.baidu.com/song/100575177/小薇.mp3"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//默认存储到临时文件夹中,需要将文件移动到其它位置
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:path] error:nil];
}];
[downloadTask resume];


5.简单上传

NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/baiduyun"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
UIImage *image = [UIImage imageNamed:@"zhaoliying.png"];
NSData *data = UIImagePNGRepresentation(image);
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionUploadTask *dataTask = [session uploadTaskWithRequest:request fromData:data completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

}];
[dataTask resume];


6.拼接表单实现文件上传

- (void)uploadNetWorkSecond {
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/baiduyun"];
NSMutableURLRequest *mulRequest = [NSMutableURLRequest requestWithURL:url];
mulRequest.HTTPMethod = @"POST";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data;boundary=%@",@"boundary"];
[mulRequest setValue:contentType forHTTPHeaderField:@"Content-Type"];
//拼接表单,filePath:要上传文件路径,formName:表单控件名称,与服务器一致,newName:上传后的文件名称
NSData *data = [self setFilePath:@"/users/yimiyangguang/Desktop/zhaoliying.png" formName:@"file" newName:@"newzhaoliying.png"];
mulRequest.HTTPBody = data;
[mulRequest setValue:[NSString stringWithFormat:@"%lu",data.length] forHTTPHeaderField:@"Content-Length"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionUploadTask *dataTask = [session dataTaskWithRequest:mulRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

}];
[dataTask resume];
}

- (NSData *)setFilePath:(NSString *)filePath formName:(NSString *)formName newName:(NSString *)newName {
NSMutableData *data = [NSMutableData data];
NSURLResponse *response = [self getLocalFileResponse:filePath];
NSString *fileType = response.MIMEType;

//表单拼接
NSMutableString *headerStr = [NSMutableString string];
[headerStr appendFormat:@"--%@\r\n",@"boundary"];
[headerStr appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n",formName,newName];
[headerStr appendFormat:@"Content-Type: %@\r\n\r\n",fileType];
[data appendData:[headerStr dataUsingEncoding:NSUTF8StringEncoding]];

NSData *fileData = [NSData dataWithContentsOfFile:filePath];
[data appendData:fileData];

NSMutableString *footerStr = [NSMutableString stringWithFormat:@"\r\n--%@--\r\n",@"boundary"];
[data appendData:[footerStr dataUsingEncoding:NSUTF8StringEncoding]];
return data;
}

//根据本地文件路径,对本地文件进行处理
- (NSURLResponse *)getLocalFileResponse:(NSString *)filePath {
filePath = [filePath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
NSURL *url = [NSURL fileURLWithPath:filePath];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
__block NSURLResponse *LocalResponse = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
LocalResponse = response;
dispatch_semaphore_signal(semaphore);
}];
[dataTask resume];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return LocalResponse;
}


经过AFNetworking的洗礼

我们之前讲过AFN的概况介绍,今天我们浅析一下AFN的封装思路,并从另一个角度讲解AFN中的技术点。

我们首先从AFNetworking的大体结构说起:

1.我们封装一个网络框架,首先需要一个类来检测当前网络环境(AFNetworkReachabilityManager):AFN提供了四种网络状态–未知、蜂窝、wifi、无网络。如果网络环境发生了改变,需要及时进行通知。

2.我们需要封装一个类来提供安全策略(AFSecurityPolicy):AFN提供了三种安全策略–公钥、证书、无。

3.我们需要封装一个类来提供请求序列化(AFURLRequestSerialization):缓存策略、cookie使用、超时时间、请求头处理等,并根据不同条件返回请求实例。

4.我们需要封装一个类来提供响应序列化(AFURLResponseSerialization):可接受的状态码、可接受的Content-Type类型、是否有效的响应,实例化响应实例。处理json、xml和其他潜在类型的类。

5.我们需要封装一个类(AFURLSessionManager),将上面的四个类进行应用,并提供网络会话及相关操作。

6.为了更好的进行HTTP的细节处理,提供子类(AFHTTPSessionManager),分别用来处理GET、POST、HEAD、PUT、PATCH、DELET方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息