iOS (二) - Http for iOS

作者: travin | 来源:发表于2016-04-05 18:58 被阅读4204次

    随说 : 在网上有很多类似的文章,可以从网上获得更多的资料,真正做项目下来,网络请求是必不可小的,特别近期在做混编这一块,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
    
    1. 请求方法就是我们所熟悉的POST、GET、HEAD、PUT 查看请求方法大全
    2. URI就是URL中排除掉Host剩下的部分,也就是资源在服务器本地上的路径
    3. HTTP版本号,目前主流的版本是1.1(1999年开始采用),最新的版本是2.0(2015年5月发布)。不同版本之间差异下面会再展开

    在IOS中 :
    HTTP请求在iOS中用NSURLRequest与NSMutableRequest表示;HTTP响应用NSHTTPURLResponse表示。

    请求头###

    一个请求中含有的信息 : 下面是请求baidu

    1. Host: 目标服务器的网络地址
    2. Accept: 让服务端知道客户端所能接收的数据类型,如text/html /
    3. Content-Type: body中的数据类型,如application/json; charset=UTF-8
    4. Accept-Language: 客户端的语言环境,如zh-cn
    5. Accept-Encoding: 客户端支持的数据压缩格式,如gzip
    6. 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
    7. Connection: keep-alive,该字段是从HTTP1.1才开始有的,用来告诉服务端这是一个持久连接,“请服务端不要在发出响应后立即断开TCP连接”。关于该字段的更多解释将在后面的HTTP版本简介中展开。
    8. Content-Length: body的长度,如果body为空则该字段值为0。该字段一般在POST请求中才会有。
    9. 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类提供了什么方法

    1. 有两个类NSURLRequest与NSMutableRequest
    2. 其中NSURLRequest是继承 NSObject的 NSMutableRequest是继承NSURLRequest
    3. 另外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(主流版本)比之前的版本多了几种新特性

    1. 增加请求头跟响应头,用于自定义整个链接过程中的一些行为
    2. 支持持久连接。客户端通过请求头中指定Connection为keep-alive告知服务端不要在完成响应后立即释放连接。HTTP是基于TCP的,在HTTP 1.1中一次TCP连接可以处理多次HTTP请求
    3. 客户端异步请求。打断请求与请求之间依赖关系,更好地利用资源,增加效率,有点类似多线程的异步处理。

    由上图可以知道, 发送请求报文和接收响应报文,都必须在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

    1. HTTP是短连接,尽管HTTP1.1开始支持持久连接,但仍无法保证始终连接。因为有超时的机制, 特定时间之后链接建立的链接即会超时, 超时之后TCP链接自动发送断开链接请求并且断开链接.
    2. HTTP采用“请求-响应”机制,在客户端还没发送消息给服务端前,服务端无法推送消息给客户端。必须满足客户端发送消息在前,服务端回复在后。,也就是说, "没请求,没交流"
    3. HTTP连接的是服务器与客户端之间的 点对多关系, 多个客户端对同一服务器发出请求, 然后服务器根据请求将相应返回给相应的客户端
    4. Socket(基于TCP协议的)是长连接,长连接的意思是指,连接时间长,Socket连接一旦建立TCP三次握手,除非一方主动断开,否则连接状态一直保持。
    5. Socket有两种模式,流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。基于TCP协议的socket连接同样需要通过三次握手建立连接,是可靠的;基于UDP协议的socket连接不需要建立连接的过程,不过对方能不能收到都会发送过去,是不可靠的,大多数的即时通讯IM都是后者。
    6. 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

    相关文章

      网友评论

      本文标题:iOS (二) - Http for iOS

      本文链接:https://www.haomeiwen.com/subject/ggvplttx.html