iOS (二) - Http for iOS
随说 : 在网上有很多类似的文章,可以从网上获得更多的资料,真正做项目下来,网络请求是必不可小的,特别近期在做混编这一块,H5与objective-c的混编,抓取网页,分析网页数据展示,缓存,离线读取等.
HTTP协议是网络请求的基本协议,在项目中我们经常需要往服务端发POST或者GET请求,下面我将总结一下.
HTTP是什么?##
HTTP本质上是一种协议,全称是Hypertext Transfer Protocol,即超文本传输协议。从名字上可以看出该协议用于规定客户端与服务端之间的传输规则,所传输的内容不局限于文本(其实可以传输任意类型的数据)。
HTTP是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型。HTTP是一个无状态的协议。
Http请求是什么?##
你的app需要数据的时候,就需要去获取数据,问服务器拿数据就是通过发送请求以告诉服务器你想要什么,那么这里面包含的信息需要遵守Http的协议,统称为请求行
请求行###
请求行包含请求方法(Method)、请求统一资源标识符(URI)、HTTP版本号
例如请求百度的Logo图片
Method:GET URL:https://m.baidu.com/static/search/baiduapp_icon.png/ HTTP1.1
- 请求方法就是我们所熟悉的POST、GET、HEAD、PUT 查看请求方法大全
- URI就是URL中排除掉Host剩下的部分,也就是资源在服务器本地上的路径
- HTTP版本号,目前主流的版本是1.1(1999年开始采用),最新的版本是2.0(2015年5月发布)。不同版本之间差异下面会再展开
在IOS中 :
HTTP请求在iOS中用NSURLRequest与NSMutableRequest表示;HTTP响应用NSHTTPURLResponse表示。
请求头###
一个请求中含有的信息 : 下面是请求baidu
- Host: 目标服务器的网络地址
- Accept: 让服务端知道客户端所能接收的数据类型,如text/html /
- Content-Type: body中的数据类型,如application/json; charset=UTF-8
- Accept-Language: 客户端的语言环境,如zh-cn
- Accept-Encoding: 客户端支持的数据压缩格式,如gzip
- User-Agent: 客户端的软件环境,我们可以更改该字段为自己客户端的名字,比如百度
User-Agent : Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1 - Connection: keep-alive,该字段是从HTTP1.1才开始有的,用来告诉服务端这是一个持久连接,“请服务端不要在发出响应后立即断开TCP连接”。关于该字段的更多解释将在后面的HTTP版本简介中展开。
- Content-Length: body的长度,如果body为空则该字段值为0。该字段一般在POST请求中才会有。
- Cookie: 记录者用户信息的保存在本地的用户数据,如果有会被自动附上
请求体###
真正需要发给服务端的数据,在使用POST-multipart上传请求中请求体就是上传文件的二进制NSData类型数据;在GET请求中请求体为空;在普通的POST请求中请求体就是一些表单数据。
NSURLRequest中提供请求体,只读
// 在NSURLRequest中, 该属性只能读取,所以不能通过setHTTPBody修改
@property (nullable, readonly, copy) NSData *HTTPBody;
@property (nullable, readonly, retain) NSInputStream *HTTPBodyStream;
NSMutableURLRequest中提供了几个属性标识Request中的请求体
// 在NSMutableURLRequest中, 该属性是是请求体的数据,可以通过setHTTPBody来设置请求体内容
@property (nullable, copy) NSData *HTTPBody;
@property (nullable, retain) NSInputStream *HTTPBodyStream;
IOS中对应请求的NSURLRequest类提供了什么方法
- 有两个类NSURLRequest与NSMutableRequest
- 其中NSURLRequest是继承 NSObject的 NSMutableRequest是继承NSURLRequest
- 另外NSURLRequest遵守<NSSecureCoding, NSCopying, NSMutableCopying>协议
NSMutableRequest中提供了几个方法允许修改Request中的请求头
// 为请求头增加字段, field名字要严格遵守协议
- (void)addValue:(NSString *)value forHTTPHeaderField:(NSString *)field
// 根据field修改设置value, field要严格遵守http协议
- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field
// 根据field的名字获取请求头的字段
- (nullable NSString *)valueForHTTPHeaderField:(NSString *)field;
// 还有一个属性, 存储该请求所有请求头信息
@property(copy) NSDictionary <NSString *,NSString *> *allHTTPHeaderFields
Http响应是什么?
响应与请求一样,客户端将请求发送到服务器后,服务器会根据请求的内容返回"内容",这个"内容"就叫做响应
响应由响应状态,响应头,响应实体组成
响应状态###
下面这个是典型的响应状态
HTTP/1.1 200 OK
响应头###
响应头和请求头基本一样, 详细可以查看 查看更多响应头信息
响应实体###
请求体也是一样.
IOS中对应请求的NSURLResponse类提供了什么方法
// 只读 , 响应状态
@property (readonly) NSInteger statusCode;
// 只读 , 响应请求头
@property (readonly, copy) NSDictionary *allHeaderFields;
// 只读 , 响应对应的URL
@property (nullable, readonly, copy) NSURL *URL;
// 只读 , 响应对应的MIMEType, 关于这个类型不用死记,需要的时候再找
@property (nullable, readonly, copy) NSString *MIMEType;
注意,因为响应实体在IOS中转换为NSData,所以通过NSURLConnection(IOS9后调用NSURLSession)间接拿到response的数据,请求与响应之间建立的链接就是利用了NSURLConnection(NSURLSession)类
HTTP的请求与响应之间是如何连接的?##
HTTP 1.1(主流版本)###
HTTP 1.1(主流版本)比之前的版本多了几种新特性
- 增加请求头跟响应头,用于自定义整个链接过程中的一些行为
- 支持持久连接。客户端通过请求头中指定Connection为keep-alive告知服务端不要在完成响应后立即释放连接。HTTP是基于TCP的,在HTTP 1.1中一次TCP连接可以处理多次HTTP请求
- 客户端异步请求。打断请求与请求之间依赖关系,更好地利用资源,增加效率,有点类似多线程的异步处理。
由上图可以知道, 发送请求报文和接收响应报文,都必须在TCP已经成功连接的基础上进行的, 而HTTP 1.0版本中, 是没有持久连接的概念,也就是说以前是request - response 一次之后,TCP连接马上会断开. 下一次的request - response又会再次连接断开.持久连接很好地解决了这个问题.
几种概念的混淆(HTTP、Socket、TCP的区别)###
HTTP协议只是应用层的一个协议而尔,所以HTTP协议是基于TCP / IP的
先要知道的是TCP/IP是一个协议族,这是一套协议的集合, TCP/IP 是 OSI 七层协议的"封装"
而TCP只是 TCP/IP协议族中传输层的一个协议, 同一层中(传输层)中还有UDP协议
socket层只是在TCP/UDP传输层上做的一个抽象接口层,因此一个socket连接可以基于TCP,也有可能基于UDP。(TCP就是流式Socket, UDP就是数据报式Socket(SOCK_DGRAM))
区分好Http 与 Socket
- HTTP是短连接,尽管HTTP1.1开始支持持久连接,但仍无法保证始终连接。因为有超时的机制, 特定时间之后链接建立的链接即会超时, 超时之后TCP链接自动发送断开链接请求并且断开链接.
- HTTP采用“请求-响应”机制,在客户端还没发送消息给服务端前,服务端无法推送消息给客户端。必须满足客户端发送消息在前,服务端回复在后。,也就是说, "没请求,没交流"
- HTTP连接的是服务器与客户端之间的 点对多关系, 多个客户端对同一服务器发出请求, 然后服务器根据请求将相应返回给相应的客户端
- Socket(基于TCP协议的)是长连接,长连接的意思是指,连接时间长,Socket连接一旦建立TCP三次握手,除非一方主动断开,否则连接状态一直保持。
- Socket有两种模式,流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。基于TCP协议的socket连接同样需要通过三次握手建立连接,是可靠的;基于UDP协议的socket连接不需要建立连接的过程,不过对方能不能收到都会发送过去,是不可靠的,大多数的即时通讯IM都是后者。
- Socket连接的是更多就是点对点的关系了, Socket数据结构中包含这五种信息,(通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口), 所以更多的是一种 点对点的关系。
后记##
在IOS的体系中,建立Http连接的,一般用源生的NSURLConnection,(IOS7之后,用的NSURLSession),当然更多的是用AFNetWorking框架来发送请求
如果建立Socket连接,一般用CocoaAsyncSocket.
关于这两个大型框架的用法,后面我会贴出来在总结一下的.感谢查看
系列的其他整理
[IOS混合编程 - UIWebView 与 WKWebView . 基本使用 (一)][4]
[IOS混合编程 - Http for IOS (二)][5]
[IOS混合编程 - NSURLProtocol 的使用 (三)][6]
[4]: http://www.jianshu.com/p/b3e7fa514ab7
[5]: http://www.jianshu.com/p/a6830a9287d6
[6]: http://www.jianshu.com/p/ec5d6c204e17