iOS网络编程
2018-11-05 本文已影响3人
CoderRH
一、URL
URL的全称是Uniform Resource Locator(统一资源定位符),通过1个URL,能找到互联网上唯一的1个资源,URL就是资源的地址、位置,互联网上的每个资源都有一个唯一的URL
的基本格式 = 协议://主机地址/路径,示例:
http://www.baidu.com/img/logo.png
http://111.111.111.111/img/bdlogo.gif协议、主机地址、路径的含义:
协议:不同的协议,代表着不同的资源查找方式、资源传输方式
主机地址:存放资源的主机(服务器)的IP地址(域名)
路径:资源在主机(服务器)中的具体位置
二、HTTP协议
1.HTTP协议简介
- HTTP的全称是Hypertext Transfer Protocol,超文本传输协议
- 规定客户端和服务器之间的数据传输格式
- 让客户端和服务器能有效地进行数据沟通
2.HTTP协议特点
- 简单快速:因为HTTP协议简单,所以HTTP服务器的程序规模小,因而通信速度很快
- 灵活:HTTP允许传输各种各样的数据
- HTTP 0.9和1.0使用非持续连接:限制每次连接只处理一个请求,服务器对客户端的请求做出响应后,马上断开连接,这种方式可以节省传输时间
3.HTTP协议的请求方法
- 在HTTP/1.1协议中,定义了8种发送http请求的方法:GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH
- PUT :增、DELETE :删、POST:改、GET:查
- 最常用的是GET和POST(实际上GET和POST都能办到增删改查)
4.GET和POST
4.1、GET
- 在请求URL后面以?的形式跟上发给服务器的参数,多个参数之间用&隔开,比如:http://ww.test.com/login?username=123&pwd=234&type=JSON
- 由于浏览器和服务器对URL长度有限制,因此在URL后面附带的参数是有限制的,通常不能超过1KB
- 如果仅仅是索取数据(数据查询),建议使用GET
4.2、POST
- 发给服务器的参数全部放在请求体中
- 理论上,POST传递的数据量没有限制(具体还得看服务器的处理能力)
- 如果要传递大量数据,比如文件上传,只能用POST请求
- GET的安全性比POST要差些,如果包含机密\敏感信息,建议用POST
- 如果是增加、修改、删除数据,建议使用POST
5、iOS中发送HTTP请求的方案
5.1、苹果原生(自带)
- NSURLConnection:用法简单,最古老最经典最直接的一种方案【坑比较多】
- NSURLSession:功能比NSURLConnection更加强大,苹果目前比较推荐使用这种技术【2013推出,iOS7开始出的技术】
- CFNetwork:NSURL*的底层,纯C语言
5.2、第三方框架
- ASIHttpRequest:外号“HTTP终结者”,功能极其强大,可惜早已停止更新
- AFNetworking:简单易用,提供了基本够用的常用功能,维护和使用者多
- MKNetworkKit:简单易用,维护和使用者少
6、HTTP通信过程
6.1、请求
- HTTP协议规定:1个完整的由客户端发给服务器的HTTP请求中包含以下内容
- 请求头:包含了对客户端的环境描述、客户端请求信息等
- GET /minion.png HTTP/1.1 // 包含了请求方法、请求资源路径、HTTP协议版本
- Host: 120.25.226.186:32812 // 客户端想访问的服务器主机地址
- User-Agent: Mozilla/5.0 // 客户端的类型,客户端的软件环境
- Accept: text/html, / // 客户端所能接收的数据类型
- Accept-Language: zh-cn // 客户端的语言环境
- Accept-Encoding: gzip // 客户端支持的数据压缩格式
- 请求体:客户端发给服务器的具体数据,比如文件数据(POST请求才会有)
6.2、响应
- 客户端向服务器发送请求,服务器应当做出响应,即返回数据给客户端
- HTTP协议规定:1个完整的HTTP响应中包含以下内容:
- 响应头:包含了对服务器的描述、对返回数据的描述:
- HTTP/1.1 200 OK // 包含了HTTP协议版本、状态码、状态英文名称
- Server: Apache-Coyote/1.1 // 服务器的类型
- Content-Type: image/jpeg // 返回数据的类型
- Content-Length: 56811 // 返回数据的长度
- Date: Mon, 23 Jun 2014 12:54:52 GMT // 响应的时间
- 响应体:服务器返回给客户端的具体数据,比如文件数据
6.3、常见的响应状态码
常见服务器响应的状态码三、NSURLConnection
1、NSURLConnection的使用步骤
- 创建一个NSURL对象,设置请求路径
- 传入NSURL创建一个NSURLRequest对象,设置请求头和请求体(POST请求的时候使用NSMutableURLRequest设置请求体,GET和POST请求头已经默认设置好了)
- 使用NSURLConnection发送请求
1.1、NSURLConnection使用图示
NSURLConnection使用图示2.NSURLConnection实际使用
2.1、NSURLConnection的基本使用
//发送异步请求:不会卡住当前线程
- (void)async{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", string);
//获取响应头信息
NSHTTPURLResponse *r = (NSHTTPURLResponse *)response;
NSLog(@"%zd %@", r.statusCode, r.allHeaderFields);
}];
}
//发送同步请求:卡住当前线程,直到请求完成
- (void)sync{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=123&pwd=345"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@ %@", string, response.allHeaderFields);
}
2.2、NSURLConnection的代理方式:拿到connection对象调用cancel方法可以取消请求
- (void)delegateAysnc{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self];//自动请求
//[[NSURLConnection alloc] initWithRequest:request delegate:self];//自动请求
//startImmediately:YES:立即自动请求,NO:调用conn的start方法才会请求
//NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
}
//<NSURLConnectionDataDelegate>
// 接收到服务器的响应
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
}
//接收到服务器的数据(如果数据量比较大,这个方法会被调用多次)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
}
//服务器的数据成功接收完毕
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
}
//请求失败(比如请求超时)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
}
2.3、NSMutableURLRequest简介
//设置请求超时等待时间(超过这个时间就算超时,请求失败)
- (void)setTimeoutInterval:(NSTimeInterval)seconds;
//设置请求方法(比如GET和POST)
- (void)setHTTPMethod:(NSString *)method;
//设置请求体
- (void)setHTTPBody:(NSData *)data;
//设置请求头
- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;
2.4、NSURLConnection发送POST请求
- (void)sendPOSTRequest {
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
request.HTTPBody = [@"username=520it&pwd=520it" dataUsingEncoding:NSUTF8StringEncoding];
request.timeoutInterval = 5;
// 设置请求头
//[request setValue:@"iOS 9.0" forHTTPHeaderField:@"User-Agent"];
// 3.发送请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
}];
}
2.5、URL中文转码
//URL中包含中文的话需要进行转码,否则识别不了
- (nullable NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)enc;
四、JSON&XML
1、JSON
- 第三方框架:JSONKit、SBJson、TouchJSON(性能从左到右,越差)
- 苹果原生(自带):NSJSONSerialization(性能最好)
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
+ (NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;
2、XML
- 全称是Extensible Markup Language,译作“可扩展标记语言”,跟JSON一样,也是常用的一种用于交互的数据格式,一般也叫XML文档(XML Document)
- 一个常见的XML文档一般由以下部分组成:
文档声明
元素(Element)
属性(Attribute)
2.1、文档声明
- 在XML文档的最前面,必须编写一个文档声明,用来声明XML文档的类型
- 最简单的声明:
<?xml version="1.0" ?>- 用encoding属性说明文档的字符编码:
<?xml version="1.0" encoding="UTF-8" ?>
2.2、元素(Element)
- 一个元素包括了开始标签和结束标签
- 拥有内容的元素:<video>小黄人</video>
- 没有内容的元素:<video></video>
- 没有内容的元素简写:<video/>
一个元素可以嵌套若干个子元素(不能出现交叉嵌套)
元素嵌套- 规范的XML文档最多只有1个根元素,其他元素都是根元素的子孙元素
2.3、属性(Attribute)
- 一个元素可以拥有多个属性
<video name="小黄人 第01部" length="30" />- video元素拥有name和length两个属性
- 属性值必须用 双引号"" 或者 单引号'' 括住
3、XML的解析
3.1、DOM&SAX
- DOM:一次性将整个XML文档加载进内存,比较适合解析小文件
- SAX:从根元素开始,按顺序一个元素一个元素往下解析,比较适合解析大文件
3.2、解析方式
- 苹果原生
NSXMLParser:SAX方式解析,使用简单- 第三方框架
libxml2:纯C语言,默认包含在iOS SDK中,同时支持DOM和SAX方式解析
GDataXML:DOM方式解析,由Google开发,基于libxml2- XML解析方式的选择建议
大文件:NSXMLParser、libxml2
小文件:GDataXML、NSXMLParser、libxml2
3.3、GDataXML的配置
3.3.1、GDataXML下载地址 密码:hsfn
3.3.2、导入libxml2库:
3.3.3、设置libxml2的头文件搜索路径(为了能找到libxml2库的所有头文件):
在Head Search Path中加入/usr/include/libxml2
3.3.4、设置链接参数(自动链接libxml2库:
在Other Linker Flags中加入-lxml2
3.4、NSXMLParser解析示例:
//XML大致格式
<videos>
<video id="1" name="xxx" length="xxx" url="xxx" image= "xxx"/>
<video id="2" name="xxx" length="xxx" url="xxx" image= "xxx"/>
<video id="3" name="xxx" length="xxx" url="xxx" image= "xxx"/>
</videos>
- (void)NSXMLParserTest {
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
parser.delegate = self;
[parser parse];//会阻塞当前线程
}];
}
#pragma mark - <NSXMLParserDelegate>
//解析到某个元素的结尾(比如解析</videos>)
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
}
// 解析到某个元素的开头(比如解析<videos>)
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:@"videos"]) return;
VideoModel *video = [VideoModel objectWithKeyValues:attributeDict];
[self.videos addObject:video];
}
//开始解析XML文档
- (void)parserDidStartDocument:(NSXMLParser *)parser{
}
//解析完毕
- (void)parserDidEndDocument:(NSXMLParser *)parser{
}
3.5、GDataXML解析示例:
//XML大致格式
<videos>
<video id="1" name="xxx" length="xxx" url="xxx" image= "xxx"/>
<video id="2" name="xxx" length="xxx" url="xxx" image= "xxx"/>
<video id="3" name="xxx" length="xxx" url="xxx" image= "xxx"/>
</videos>
- (void)GDataXMLTest {
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// 加载整个文档
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil];
// 获得所有video元素
NSArray *elements = [doc.rootElement elementsForName:@"video"];
for (GDataXMLElement *ele in elements) {
VideoModel *video = [[VideoModel alloc] init];
video.name = [ele attributeForName:@"name"].stringValue;
video.url = [ele attributeForName:@"url"].stringValue;
video.image = [ele attributeForName:@"image"].stringValue;
video.length = [ele attributeForName:@"length"].stringValue.integerValue;
[self.videos addObject:video];
}
}];
}