【重读iOS】网络请求2:应用

2018-09-11  本文已影响42人  FindCrt
  1. 基础知识
  2. HTTP基础知识(状态码,请求方法,请求头,cookies)
  3. socket/webSocket
  4. 系统请求库和开源请求库
  5. 缓存系统(LRU LFU)
  6. 应用场景:文件上传,断点续传,加密和签名。
  7. 特殊请求:流媒体协议,IM长连接

系统库

以前是NSURLConnection,现在已经改版成NSURLSession为核心了。架构如图:

image

即session控制多个请求,每个请求对应为一个SessionTask,然后使用SessionConfiguration来配置session的性质。

task有4种:dataTask,downloadTask,streamTask,然后uploadTask继承于dataTask。

构建task之后通过resume方法开启,然后通过session的delegate方法回调处理请求的种种状况。

1. session构建
2. 权限验证

HTTPS知识

验证服务器的证书正确性:

//默认是让系统做默认处理
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    NSURLCredential *credential = nil;
    
    if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
        SecTrustRef secTrust = challenge.protectionSpace.serverTrust;
        
        SecTrustResultType result = 0;
        SecTrustEvaluate(secTrust, &result);
        
        if (result == kSecTrustResultProceed ||
            result == kSecTrustResultUnspecified) {
            
            credential = [[NSURLCredential alloc] initWithTrust:secTrust];
            //只有证书验证通过并且构建成功时信任证书
            if (credential) {
                disposition = NSURLSessionAuthChallengeUseCredential;
            }
        }else{
        //证书验证失败,取消信任
            disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
        }
    }
    
    completionHandler(disposition, credential);

证书分为从CA签发的证书跟自建证书两种,证书都是一级级签发的,形成一个证书链。从CA签发的证书和自建证书的区别就是前者的根证书是公开已知的,操作系统在安装过程中会默认安装一些受信任的CA机构的根证书,所以如果是第一张,系统自身就可以完成这个验证过程。

如果是自己签发的证书,系统是不认识的,要自定义认证过程。这部分可参考AFNetWorking的处理:

//替换为自己本地指定的证书
SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates);
//验证证书
if (!AFServerTrustIsValid(serverTrust)) {
    return NO;
}
3. 接收数据3件套

didReceiveResponse: didReceiveData: didCompleteWithError:

4. downloadTask
[downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
       //使用这个方法取消,获取到用于重启的数据,保存下来
   }];
 ...
 //之后使用这个resumeData重新构建下载任务
 NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithResumeData:resumeData];

从这两个特性可知:downloadTask是用来应对大的文件传输的,在这种应用环境下可考虑使用。

设计上,使用resumeData就可以重启下载,说明这个数据里至少保存了URL信息,所以猜测它的设计里,这个数据可能并不是下载的数据,而是一系列的描述信息,如URL、证书认证、之前下载的文件地址、已下载字节大小等。

可惜这里是不透明的NSData类型,断点续传的功能完全可以自己设计,还可以更好的控制下载文件位置、缓存、数据模型等。比如超级大图要求下载一部分就立马显示出来,这种需求就需要在过程中就获取数据,而这里downloadTask的delegate方法只是提供了数据大小却没有提供数据位置。

断点续传的实现

5. uploadTask和文件上传协议

使用系统的上传方法:

uploadTaskWith...系列有3个方法,抓包查看,使用uploadTaskWithRequest:fromFile:方法的请求类型为:Content-Type application/octet-stream,而另外两种为Content-Type application/x-www-form-urlencoded

对后台处理似乎没什么区别,都是从数据流里读取然后写入文件。系统的上传有很鸡肋:1. 没法同时传多个文件 2.没法同时传入其他的参数。

如果你要做这些,就要自己去构建request,那么这个uploadTask其实已经没什么作用了,就是其他类型的task照样能完成任务。

自定义上传方式:如果要解决掉上面说的两个缺点,要使用multipart/form-data的方式,具体参考iOS里实现multipart/form-data格式上传文件,或者直接使用第三方库,AFNetWorking内部就是使用这种方式上传文件。

6. 断点续传

断点续传还有一个好处是可以多线程下载数据,把大文件切割为多个部分,分多个线程分别请求,然后在本地拼接。

7. 缓存系统(LRU LFU)

参考缓存策略之LRU和LFU

上一篇 下一篇

猜你喜欢

热点阅读