【原】iOS学习39网络之数据请求
1. HTTP和HTTPS协议
1> URL
URL全称是Uniform Resource Locator(统一资源定位符)通过1个URL,能找到互联网上唯一的1个资源
URL就是资源的地址、位置,互联网上的每个资源都有一个唯一的URL
URL的基本格式=协议://主机地址/路径
http://www.cnblogs.com/gfxxbk/
协议:不同的协议,代表着不同的资源查找方式,资源传输方式
主机地址:存放资源的主机的IP地址(域名)
路径:资源在主机中的位置
2> HTTP协议的概念
HTTP协议,Hyper Text Transfer Protocol(超文本传输协议)是用于从万维网(WWW)服务器传送超文本到本地浏览器的传输协议,HTTP是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型。
3> HTTP的工作原理
HTTP 协议采用请求/响应模型。客户端向服务器发送一个请求报文,服务器以一个状态作为响应。
4> C/S模式
Client和Server常常分别处在相距很远的两台计算机上,Client程序的任务是将用户的要求提交给Server程序,再将Server程序返回的结果以特定的形式显示给用户;Server程序的任务是接收客户程序提出的服务请求,进行相应的处理,再将结果返回给客户程序
5> HTTPS
HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议 它是一个安全通信通道,它基于HTTP开发,用于在客户计算机和服务器之间交换信息。 它使用安全套接字层(SSL)进行信息交换,简单来说它是HTTP的安全版。 HTTPS协议使用SSL在发送方把原始数据进行加密,然后在接收方进行解密,加密和解密需要发送方和接受方通过交换共知的密钥来实现,因此,所传送的数据不容易被网络黑客截获和解密。
6> SSL
SSL是Netscape公司所提出的安全保密协议,在浏览器(如Internet Explorer、Netscape Navigator)和Web服务器(如Netscape的Netscape Enterprise Server、ColdFusion Server等等)之间构造安全通道来进行数据传输,SSL运行在TCP/IP层之上、应用层之下,为应用程序提供加密数据通道,
7> HTTP和HTTPS的异同
-
https协议需要到ca申请证书,一般免费证书很少,需要交费。
-
http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议
-
http和https使用的是完全不同的链接方式,用的端口也不一样,前者是80,后者是443.
-
http的链接很简单,是无状态的.
- https是协议是由SSL+HTTP协议构建的可进行加密传输,身份认证的网络协议要比http安全
2. HTTP协议的常见请求方式
1> 请求方式
-
GET
-
POST
2> 两种请求方式的比较
- 给服务器传输数据的方式不同
GET:通过网址字符串
POST:通过data
- 传输数据的大小
GET:网址字符串最多255字节
POST:使用NSData,容量超过1G
- 安全性
GET:所有传输给服务的数据,显示在网址里,类似于密码的明文输入,直接可见
POST:数据被转成NSData(二进制数据),类似于密码的密文输入,无法直接读取
3. iOS实现网络编程(iOS7之前的版本,现在已经弃用,但是仍然可以使用)
1> HTTP协议请求如何实现
网络请求地址对象NSURL的作用及用法
网络请求对象NSURLRequest,NSMutableURLRequest的作用及用法
网络链接对象NSURLConnection的作用及用法
网络链接协议NSURLConnectionDelegate的作用及用法
2> NSURL
url:统一资源定位符,也被称为网址,因特网上标准的资源网址
一个典型的url:http://lily:123456@www.google.com/search?hl=en&source=hp&q=mysql&aq=f&oq=&aqi=g10#page
url的符语法: 协议://授权/路径?查询
协议: ftp://(文件传输协议) http://(超文本传输协议)
https://(安全超文本传输协议) file://(本地文件协议)
3> 连接方式
-
同步连接:程序容易出现卡死现象
-
异步连接:等待数据返回
异步连接有两种实现方式:
① 设置代理,接收数据
② 实现block
4> 打开Xcode网络适配
使用http请求 :NSAppTransportSecurity 字典 ,NSAllowsArbitraryLoads YES
代码:
1 <key>NSAppTransportSecurity</key> 2 <dict> 3 <key>NSAllowsArbitraryLoads</key> 4 <true/> 5 </dict>
图表:
5> 同步连接
① GET同步
1 - (IBAction)getSynchronousRequest:(UIButton *)sender 2 { 3 // 1. 创建URL 4 // GET_URL 是一个get网络传值的域名 5 NSURL *url = [NSURL URLWithString:GET_URL]; 6 7 // 2. 根据URL创建具体请求(使用缓存策略) 8 // 第一个参数:URL(统一资源定位符) 9 // 第二个参数:缓存策略(枚举值) 10 /* 11 NSURLRequestUseProtocolCachePolicy = 0 基础缓存策略 12 13 NSURLRequestReloadIgnoringLocalCacheData = 1 忽略本地的缓存,所有的数据都从网络获取 14 15 NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4 如果本地有缓存且有效就从本地获取,否则从原地址下载 16 17 NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData // 优先使用本地缓存,如果没有本地缓存就从网络加载 18 19 NSURLRequestReturnCacheDataElseLoad = 2 使用本地缓存,从不下载,如果本地没有缓存,则请求失败,此策略多用于离线操作 20 21 NSURLRequestReturnCacheDataDontLoad = 3 无视任何缓存策略,无论是本地的还是远程的,总是从原地址重新下载 22 23 NSURLRequestReloadRevalidatingCacheData = 5 如果本地缓存是有效的则不下载,其他任何情况都从原地址重新下载 24 25 */ 26 // 第三个参数:设置延迟时间,如果超时,请求终止,单位为秒(s) 27 NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20]; 28 29 // 3. 连接服务器【NSURLConnection在iOS9之后被弃用,在以后的开发中很少见】 30 // 参数1:请求对象 31 // 参数2:存储一些网络请求的信息(一般为包体),一般为nil 32 // 参数3:错误信息 33 NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; 34 35 // 4. 进行JSON数据解析 36 NSDictionary *resultDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]; 37 38 NSLog(@"%@", resultDict); 39 40 // 解析数据自己写 41 }
② POST同步
1 #pragma mark - 同步的post请求 2 - (IBAction)postSynchronousRequest:(UIButton *)sender 3 { 4 // 1. 创建URL 5 NSURL *url = [NSURL URLWithString:POST_URL]; 6 7 // 2. 设置网络请求[post请求必须初始化为可变请求,因为稍后要进行一些内容设置] 8 NSMutableURLRequest *mutableRequest = [NSMutableURLRequest requestWithURL:url]; 9 10 // 2.5 设置body 11 // 创建一个连接字符串(这个内容在以后的开发中接口文档都有标注) 12 NSString *dataString = POST_BODY; 13 // 对接口字符串进行编码(这一步千万不能忘记) 14 NSData *postData = [dataString dataUsingEncoding:NSUTF8StringEncoding]; 15 // 设置请求格式为POST请求[这个地方在后面POST必须大写] 16 [mutableRequest setHTTPMethod:@"POST"]; 17 // 设置请求体(body) 18 [mutableRequest setHTTPBody:postData]; 19 20 // 3. 连接服务器 21 NSData *data = [NSURLConnection sendSynchronousRequest:mutableRequest returningResponse:nil error:nil]; 22 23 // 4. 进行JSON数据解析 24 NSDictionary *resultDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]; 25 26 NSLog(@"%@", resultDict); 27 }
注意:post方法和get方法最大的区别就是在于post方法设置请求体(body)
注意:若网址字符串URLString中若有类对象,可以使用此方法处理:[URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
7> 异步代理
代码(代码为get请求,post请求同理,只要动态实现请求体):
1 - (IBAction)getAsynchronousRequest:(UIButton *)sender 2 { 3 // 1. 创建URL 4 NSURL *url = [NSURL URLWithString:GET_URL]; 5 6 // 2. 创建请求 7 NSURLRequest *request = [NSURLRequest requestWithURL:url]; 8 9 // 方法一:使用delegate实现 10 [NSURLConnection connectionWithRequest:request delegate:self]; 11 } 12 13 #pragma mark - NSURLConnectionDataDelegate相关的代理方法 14 // 服务器开始响应 15 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 16 { 17 self.resultData = [NSMutableData data]; 18 } 19 20 // 开始接受数据 21 // 这个方法会重复执行,得到的每段数据拼接在一起就可以了 22 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 23 { 24 [self.resultData appendData:data]; 25 } 26 27 // 结束服务器 28 - (void)connectionDidFinishLoading:(NSURLConnection *)connection 29 { 30 // 进行数据解析 31 NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:self.resultData options:NSJSONReadingAllowFragments error:nil]; 32 33 NSLog(@"%@", dict); 34 }
8>异步Block
代码(代码为get请求,post请求同理,只要动态实现请求体):
#pragma mark - 异步的get请求 - (IBAction)getAsynchronousRequest:(UIButton *)sender { // 1. 创建URL NSURL *url = [NSURL URLWithString:GET_URL]; // 2. 创建请求 NSURLRequest *request = [NSURLRequest requestWithURL:url]; // 3. 连接服务器 // 方法一:Block方法实现 // 参数1:请求对象 // 参数2:线程队列 [NSOperationQueue mainQueue] 主队列 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) { // response是携带的接口信息 // data 请求下来的数据,接下来会使用到 // connectionError 错误信息 if (connectionError == nil) { // 4. 解析 NSDictionary *resultDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]; NSLog(@"dict = %@", resultDict); // 先开辟子线程解析数据,然后在主线程刷新UI } }]; }
4. iOS7之后请求变化
1> NSURLSession
在WWDC 2013中,Apple的团队对NSURLConnection进行了重构,并推出了NSURLSession作为替代。
• 支持后台运行的网络任务
• 暂停、停止、重启网络任务,不再需要 NSOpation 封装
• 请求可以使用同样的配置容器
• 不同的 session 可以使用不同的私有存储,block和代理可以同时起作用
• 直接从文件系统上传、下载
• 为了方便程序员使用,苹果提供了一个全局 session
• 所有的 任务(Task) 都是由 Session 发起的
• 所有的任务默认是挂起的,需要 Resume
2> 三种工作模式:
+ (NSURLSessionConfiguration *)defaultSessionConfiguration; 默认会话模式
+ (NSURLSessionConfiguration *)ephemeralSessionConfiguration; 瞬时会话模式
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier; 后台会话模式
3> NSURLSession支持的三种任务
对数据加载:使用NSURLSessionDataTask和NSURLSessionTask两者没有本质区别
处理下载任务使用:NSURLSessionDownloadTask
要处理上传任务使用:NSURLSessionUploadTask
4> Block方法
① GET请求
1 #pragma mark GET的block方法 2 - (void)bolckMethod 3 { 4 // 方法1:使用Block 5 6 // 1. 创建URL 7 NSURL *url = [NSURL URLWithString:GET_URL]; 8 9 // 2. 创建session对象(iOS9之后推出) 10 NSURLSession *session = [NSURLSession sharedSession]; 11 12 // 3. 创建task请求任务 13 // NSURLSession是基于任务去完成相关的事件的 14 // 参数1. 请求的URL 15 // NSURLSessionTask 所有的任务都放在这个里实现 16 // 对数据加载:使用NSURLSessionDataTask和NSURLSessionTask两者没有本质区别 17 // 处理下载任务使用:NSURLSessionDownloadTask 18 // 要处理上传任务使用:NSURLSessionUploadTask 19 NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { 20 // 4. 解析数据 21 if (error == nil) { 22 NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]; 23 NSLog(@"%@=get-block", dict); 24 } 25 }]; 26 27 // 5. 核心:启动任务【千万不能忘记】 28 // 原因:NSURLSessionTask实例出来的任务处于挂起状态,如果不启动,不会走Block里面的相关内容 29 [task resume]; 30 }
② POST请求
1 - (IBAction)postRequest:(UIButton *)sender 2 { 3 // Block方法 4 5 NSURL *url = [NSURL URLWithString:POST_URL]; 6 7 NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:url]; 8 9 NSString *dataString = POST_BODY; 10 11 NSData *postData = [dataString dataUsingEncoding:NSUTF8StringEncoding]; 12 13 [mRequest setHTTPMethod:@"POST"]; 14 15 [mRequest setHTTPBody:postData]; 16 17 NSURLSession *sessin = [NSURLSession sharedSession]; 18 19 NSURLSessionTask *task = [sessin dataTaskWithRequest:mRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { 20 21 if (error == nil) { 22 NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]; 23 NSLog(@"%@=post-block", dict); 24 } 25 }]; 26 27 [task resume]; 28 }
5> delegate方法
代码(GET请求):
1 #pragma mark GET的delegate方法 2 - (void)delegateMethod 3 { 4 // 方法2:使用代理实现 5 // 1. 创建URL 6 NSURL *url = [NSURL URLWithString:GET_URL]; 7 8 // 2. 创建session 9 // 参数1:模式设置 10 /* 11 + (NSURLSessionConfiguration *)defaultSessionConfiguration; 默认会话模式 12 + (NSURLSessionConfiguration *)ephemeralSessionConfiguration; 瞬时会话模式 13 + (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier; 后台会话模式 14 */ 15 // 参数2:代理 16 // 参数2:线程队列模式 17 NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]]; 18 19 // 3. 创建task对象 20 NSURLSessionDataTask *task = [session dataTaskWithURL:url]; 21 22 // 4. 启动任务 23 [task resume]; 24 } 25 26 #pragma mark NSURLSessionDelegate协议方法 27 // 服务器开始响应 28 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler 29 { 30 // 允许服务器响应【在这里只允许服务器响应了才会接受到这个数据】 31 completionHandler(NSURLSessionResponseAllow); 32 // 初始化data,稍后进行片段的拼接存储 33 self.resultData = [NSMutableData data]; 34 } 35 36 // 接受数据拼接 37 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data 38 { 39 // 反复执行,然后拼接数据 40 [self.resultData appendData:data]; 41 } 42 43 // 数据接受完成,网络请求结束 44 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error 45 { 46 // 解析 47 if (error == nil) { 48 NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:self.resultData options:NSJSONReadingAllowFragments error:nil]; 49 NSLog(@"%@=get-delegate", dict); 50 } 51 }
6> NSURLSession数据任务
适合于小的数据访问,例如:JSON,XML,Plist,HTML,图像