iOS 网络编程

 

1、网络编程的基本概念

在网络编程中,有几个必须掌握的基本概念:php

  • 客户端(Client):移动应⽤(iOS,Andorid等应⽤)
  • 服务器(Server):为客户端提供服务、提供数据、提供资源的机器
  • 请求(Request):客户端向服务器索取数据的⼀种行为
  • 响应(Response):服务器对客户端的请求作出的反应,通常指返回数据给客户端

2、URL

2.1 基本介绍

URL的全称是Uniform Resource Locator(统⼀资源定位符)html

经过1个URL,能找到互联网上惟一的1个资源git

URL就是资源的地址、位置,互联网上的每一个资源都有一个惟一的URLgithub

URL的基本格式 = 协议://主机地址/路径http://61.144.56.195/forum/201302/19/144736txfrcuyvmustucmv.jpghttp://www.fzlu.com/uploads/allimg/140107/1-14010G22134235.jpgweb

解释以下: 编程

  • 协议:不一样的协议,表明着不一样的资源查找方式、资源传输方式,好比经常使用的http,ftp等
  • 主机地址:存放资源的主机的IP地址(域名)
  • 路径:资源在主机中的具体位置
  • 参数:参数无关紧要,也能够多个。若是带参数的话,用“?”号后面接参数,多个参数的话之间用&隔开

2.2 URL中常见的协议

a.HTTP:超文本传输协议,访问的是远程的网络资源,格式是http:// http协议是在网络开发中最经常使用的协议json

b.file:访问的是本地计算机上的资源,格式是file://(不用加主机地址)api

c.mailto:访问的是电子邮件地址,格式是mailto:浏览器

d.FTP:访问的是共享主机的⽂文件资源,格式是ftp://缓存

2.3 URL的请求方式

网络请求方式有两种:GET 和 POST

两种方式的相同点是:都能给服务器传输数据

两种请求方式的不一样点是:

2.3.1 给服务器传输数据的方式

  GCT:经过网址字符串

  POST:经过data

2.3.2 传输数据的大小

  GET:网址字符串最多255字节

  POST:使用NSData,容量超过1G

2.3.3 安全性

GET:全部传输给服务器的数据,显示在网址里,相似于密码的明文输入,直接可见

POST:数据被转成NSData(二进制数据),相似于密码的密文输入,没法直接读取

链接方式

同步链接:程序容易出现卡死现象

总结:同步链接请求可让你可以从因特网请求数据,一旦发送同步请求后,程序将中止用户交互,直至服务器返回数据完成才可进行下一步操做。

异步连接:等待数据返回

异步连接有两种实现方式:1.设置代理,接受数据

                                           2.实现block

2.4 总结GET的特色和POST的特色

GET的特色:

1. GET是"获取"指定URL上的资源。

2. 其将数据按照varialbe = value的形式,添加action到所指向的URL后面,而且二者使用"?"链接,各个变量之间用"&"链接。

3. 不安全,由于在传输过程当中,数据被放在请求的URL中。这样很容易被人拿到看见数据信息。

4.传输的数据量比较小

POST的特色:

1. POST语意是指对指定内容添加和追加数据(经过数据体的形式)

2. 将数据放在数据体中,按照变量和值相对应的方式,传递到action所指向的URL

3. 全部的数据对用户不可见,也就是从URL中看不到。

4. 能够传输大量数据,传输文件只能用POST

5. 不过对服务器来讲,接收数据体可能会不安全

 3、HTTP协议

3.1 HTTP协议的概念

HTTP协议,Hyper Text Transfer Protocol (超文本传输协议)是用于从万维网服务器传送超文本到本地浏览器的传输协议,HTTP是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型。

HTTP协议的做⽤

HTTP的全称是Hypertext Transfer Protocol,超文本传输协议

(1)规定客户端和服务器之间的数据传输格式

(2)让客户端和服务器能有效地进行数据沟通

HTTP的通讯过程

要想使用HTTP协议向服务器索取数据,得先了解HTTP通讯的完整过程 完整的http通讯能够分为2大步骤

(1)请求:客户端向服务器索要数据

(2)响应:服务器返回客户端相应的数据

3.2 HTTP通讯过程:请求和响应

3.2.1 HTTP请求

HTTP协议规定,1个完整的由客户端发给服务器的HTTP请求中包含如下内容

  • 请求行:包含了请求方法、请求资源路径、HTTP协议版本 GET /MJServer/resources/images/1.jpg HTTP/1.1

  • 请求头:包含了对客户端的环境描述、客户端请求的主机地址等信息

  • Host: 192.168.1.105:8080 // 客户端想访问的服务器主机地址

  • User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9) Firefox/30.0// 客户端的 类型,客户端的软件环境
  • Accept: text/html, /// 客户端所能接收的数据类型 Accept-Language: zh-cn // 客户端的语言环境
  • Accept-Encoding: gzip // 客户端支持的数据压缩格式 请求体:客户端发给服务器的具体数据,好比文件数据

3.2.2 HTTP响应

客户端向服务器发送请求,服务器应当作出响应,即返回数据给客户端

HTTP协议规定:1个完整的HTTP响应中包含如下内容:

状态行:包含了HTTP协议版本、状态码、状态英⽂名称HTTP/1.1 200 OK
响应头:包含了对服务器的描述、对返回数据的描述 Server: Apache-Coyote/1.1 // 服务器的类型
Content-Type: image/jpeg // 返回数据的类型
Content-Length: 56811 // 返回数据的长度
Date: Mon, 23 Jun 2014 12:54:52 GMT // 响应的时间 实体内容:服务器返回给客户端的具体数据,⽐好比⽂件数据

发送HTTP请求的⽅法

  • 简单说明

在HTTP/1.1协议中,定义了8种发送http请求的⽅方法 GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH 根据HTTP协议的设计初衷,不一样的方法对资源有不一样的操做⽅方式
PUT :增

DELETE :删
POST:改
GET:查 提示:最经常使用的是GET和POST(实际上GET和POST都能办到增删改查)

 get和post的选择

(1)若是要传递大量数据,⽐如⽂件上传,只能用POST请求

(2)GET的安全性比POST要差些,若是包含机密\敏感信息,建议⽤用POST

(3)若是仅仅是索取数据(数据查询),建议使用GET

(4)若是是增长、修改、删除数据,建议使用POST

3.3 http请求的基本流程

• 构造NSURL实例(地址)

• ⽣成NSURLRequest请求(网络请求的信息)

• 经过NSURLConnection发送请求

• 经过返回NSURLRespond实例和NSError实例分析结果

 • 处理返回数据

3.3.1 GET请求

GET请求:获取数据,把参数以URL的形式拼接传给服务器,以 ? 分开URL地址和参数,& 拼接多个参数

1.建立一个URL

NSString *urlStr = @"https://route.showapi.com/213-4?showapi_appid=24110&showapi_timestamp=20160905154834&topid=5&showapi_sign=5d1ba1725827501e32238072e5960958";

    NSURL *URL = [NSURL URLWithString:urlStr];

2.建立一个NSURLRequest 请求

NSURLRequest *request = [NSURLRequest requestWithURL:URL];

三、建立NSURLSession

NSURLSession *session = [NSURLSession sharedSession];

四、由session建立一个请求数据的任务NSURLSessionDataTask(会以异步的形式发送网络请求,不会阻塞主线程)

NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        // 执行完后 以block 返回结果,解析数据
      id jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];

        NSLog(@"%@",jsonData);

    }];

五、开始执行网络任务

[dataTask resume];

3.3.2  POST请求

POST请求时要指明请求的方式HTTPMethod 为 POST,参数以请求体 HTTPMethod 的形式传入。

一、设置请求方式为 POST

NSURL *url = [NSURL URLWithString:@"https://route.showapi.com/213-4"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    request.HTTPMethod = @"POST";

二、设置请求体:把参数做为NSData类型传入

NSString *parmStr = [NSString stringWithFormat:@"showapi_appid=%@&showapi_timestamp=%@&topid=%@&showapi_sign=%@",APPID,@"20160905154834",@"5",SIGN];

    request.HTTPBody = [parmStr dataUsingEncoding:NSUTF8StringEncoding];

3.建立一个NSURLRequest 请求

NSURLSession *session = [NSURLSession sharedSession];

四、由session建立一个请求数据的任务NSURLSessionDataTask(会以异步的形式发送网络请求,不会阻塞主线程)

 

NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        if (error) {
            NSLog(@"%@",error);
            return;
        }        
        // NSLog(@"%@",response);

        // 执行完后 以block 返回结果,解析数据
    id jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];

        NSLog(@"%@",jsonData);        
    }];
     //开始执行网络请求
    [dataTask resume];

4、缓存策略(NSURLRequestCachePolicy) 

4.1 缓存策略基本概念

NSURLRequest的cachePolicy属性能够设置缓存策略,这是⼀种内存缓存,⾮硬盘缓存。使用缓存的目的是为了使⽤的应用程序能更快速的响应⽤户输入,使程序高效的运行。有时候咱们须要将远程web服务器获取的数据缓存起来,减小对同⼀个url屡次请求。

4.2 设置缓存策略:cachePolicy

// 默认,使用缓存,当下一次请求时先判断是否有缓存,有就使用缓存没有才进行网络请求,使用缓存时会先判断缓存是否过时,过时的就从新请求网络。
     NSURLRequestUseProtocolCachePolicy = 0, 
     // 忽略缓存,不使用缓存
     NSURLRequestReloadIgnoringLocalCacheData = 1, 
     // 无视任何的缓存策略,不管是本地的仍是远程的,老是从原地址从新下载 
     NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, 
     NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
     //首先使用缓存不论是否过时,若是没有本地缓存,才从原地址下载
     NSURLRequestReturnCacheDataElseLoad = 2, 
     //使用本地缓存,从不下载,若是本地没有缓存,则请求失败。此策略多用于离线操做
     NSURLRequestReturnCacheDataDontLoad = 3, 
     //缓存数据必须得获得服务端确认有效才使用(NSURLRequestUseProtocolCachePolicy中的一种状况)
     // Unimplemented
     NSURLRequestReloadRevalidatingCacheData = 5,

timeoutInterval: 设置请求超时的时间秒数

NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:10];

NSURLSessionConfiguration:配置网络请求

// 默认的模式,能够缓存数据(默认会话模式)
     defaultSessionConfiguration, 
     //无痕浏览,不会有任何的缓存(瞬间会话模式)
     ephemeralSessionConfiguration, 
     //后台会话模式(该模式在后台完成上传和下载,在建立Configuration对象的时候须要提供一个NSString类型的ID用于标识完成工做的后台会话。)
     backgroundSessionConfigurationWithIdentifier

    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];

经过 NSURLSessionConfiguration 设置缓存策略

configuration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];

5、NSURLSession下载与上传

5.1 NSURLSession基本概念

  NSURLSession是为了代替NSURLConnection而设计的。Sessions的全部工做都是经过NSURLSessionTask (NSURLsessionTask 是一个抽象类,其中有 3 个实体子类能够直接使用:NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTask。这 3 个子类封装了现代程序三个最基本的网络任务:获取数据,好比 JSON 或者 XML,上传文件和下载文件。)实现的。可使用block,delegate,或者二者混合来建立task。(举个例子,你要下载图片,就要建立NSURLSessionDownloadTask。)

5.2 block方式下载

建立URL

NSURL *url = [NSURL URLWithString:@"http://dl.stream.qqmusic.qq.com/108051051.mp3?vkey=4A95A0FCDFDC050E9D543841CA4A28AABD19F1973177DAB509EEBED09344D0A91A286D0800E7C58751A670CC429DB1118C98F8908C487284&guid=2718671044"];

建立Session并设置

NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

建立一个下载任务

NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        if (error) {
            return;
        }

        // 设置保存文件的本地URL
        NSURL *docmentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        //拼接一个数据名,response suggestedFilename 自动获取下载数据的名字.格式类型
        NSURL *dataURL = [docmentsURL URLByAppendingPathComponent:[response suggestedFilename]];

        NSError *moveError = nil;
        // 将下载的数据从临时URL移动到指定的URL
        [[NSFileManager defaultManager] moveItemAtURL:location toURL:dataURL error:&moveError];
        if (!moveError) {

            NSLog(@"保存成功");
        }

        NSLog(@"%@",location);

    }];

启动下载

[downloadTask resume];

代理的方式下载

NSURL *url = [NSURL URLWithString:@"https://github.com/AFNetworking/AFNetworking/archive/master.zip"];
    
    //配置NSURLSession并设置代理,delegateQueue:代理执行的线程
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    NSURLSessionDownloadTask *downTask = [session downloadTaskWithURL:url];
     // 启动下载
    [downTask resume];

 下载完成后调用

//下载完成后调用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    
    NSLog(@"下载完成 %@",NSHomeDirectory());
    
    // 设置保存文件的本地URL
    NSURL *docmentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    NSURL *dataURL = [docmentsURL URLByAppendingPathComponent:downloadTask.response.suggestedFilename];
    
    NSError *moveError = nil;
    //将下载的数据从临时URL移动到指定的URL
    [[NSFileManager defaultManager] moveItemAtURL:location toURL:dataURL error:&moveError];
    if (!moveError) {
        
        NSLog(@"保存成功");
    }
}

 监听下载进度

// 监听下载进度
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    
    // bytesWritten: 时间点下载的数据大小 totalBytesWritten:已经下载的数据大小,totalBytesExpectedToWrite: 下载文件的总大小
    
    self.prograssView.prograss = (CGFloat)totalBytesWritten / (CGFloat)totalBytesExpectedToWrite;
    
    NSLog(@"%lld, %lld, %lld ",bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
}

5.2 文件上传

文件上传也有block和代理两种方式

  • 文件上传的时候须要设置请求头中Content-Type类型, 必须使用URL编码

 block方式上传

 建立URL

NSURL *url = [NSURL URLWithString:@"http://www.imageshack.us/index.php"];

建立请求 

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:20];

设置请求为POST 

request.HTTPMethod = @"POST";

设置请求头的上传文件的内容格式(Content-Type) 为图片类型(image/jpeg)

[request setValue:@"image/jpeg" forHTTPHeaderField:@"Content-Type"];

设置请求头的响应(Accept)的文本格式(text/html)

[request setValue:@"text/html" forHTTPHeaderField:@"Accept"];

    NSURLSession *session  = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

上传方式一:把要上传的数据保存为NSData

NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"image7.jpeg"], 0.5);

     NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:imageData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

     if (error) {
     NSLog(@"%@",error);

     } else {

     NSString *reuslt = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

     NSLog(@"%@ \n%@",response, reuslt);
     }

     }];

上传方式二:使用文件所在的本地的URL

NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"image7" withExtension:@"jpeg"];

    // NSURL *fileURL = [NSURL URLWithString:@"http://img.ivsky.com/img/tupian/pre/201507/01/yindian_meinv-001.jpg"];
    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:fileURL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        if (error) {
            NSLog(@"%@",error);

        } else {

            NSString *reuslt = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

            NSLog(@"%@ \n%@",response, reuslt);
        }         
    }];
    // 恢复线程,启动任务
   [uploadTask resume];

6、后台下载

6.1 后台下载的基本概要

 NSURLSession 支持程序的后台下载和上传, 苹果官方将其称之进程以外的上传和下载, 这些任务都交给后台守护线程完成, 而不是应用自己, 即便文件在下载和上传过程当中崩溃了也能够继续运行(若是用户强制关闭程序的话, NSURLSession会断开链接)

6.2 后台下载代码以下

签定代理协议

@interface ViewController ()<NSURLSessionDownloadDelegate>

建立URL和请求

NSURL *url = [NSURL URLWithString:@"https://github.com/fuqinglin/MagicalRecord/archive/master.zip"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:20];

设置网络请求为 backgroundSessionConfigurationWithIdentifier 后台模式,后面接标识符

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.tens.background"];

建立NSURLSession

NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];

 启动下载任务

[downloadTask resume];

 

// 后台下载完调用
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
    
    NSLog(@"后台下载完成");
    
    AppDelegate *delegate = [UIApplication sharedApplication].delegate;
    
    // 回调 AppDelegate 中 application: handleEventsForBackgroundURLSession: completionHandler: 中的block事件,处理下载完后的提示
    if (delegate.backgroundCompletionHandler) {
        
        void (^completionHandler)() = delegate.backgroundCompletionHandler;
        
        completionHandler();
    
    }
}

6.3 拓展知识点

NSURLSessionDownloadTask支持取消下载,能够在下载过程当中随时取消继续下载,同时也能够实现恢复下载。

  • 取消下载 cancelByProducingResumeData

    //用当前NSURLSessionDownloadTask对象去调用取消下载
    
       [self.downTask cancelByProducingResumeData:
        ^(NSData * _Nullable resumeData) {
    
        //全局变量 接收当前下载的资源
        self.data = resumeData;
        }
        //将当前下载任务置为空
        self.downTask = nil;
  • 恢复下载 downloadTaskWithResumeData

    //恢复下载 其实是创建了一个新的下载任务 去继续以前的下载
    
    self.downTask = [self.downLoadSession downloadTaskWithResumeData:self.data];
    
       //开启任务     
      [self.downTask resume];
    
        }
相关文章
相关标签/搜索