HTTP in iOS你看我就够

HTTP属于老话题了,在项目中咱们常常须要往服务端发POST或者GET请求,可是对于HTTP的了解不该只局限于此。千里之行,始于足下。越想走的远,基本原理就应该了解的透彻全面一些,仅仅停留在使用ASIHttpRequest或者AFNetWorking传个参数发个请求的程度上是不够的。这篇文章就是带你全方面回顾一下HTTP。html

经过本文你能收获哪些内容:git

  • 完整HTTP请求与响应包含的必要元素github

  • HTTP不一样版本之间的差别json

  • HTTP、Socket、TCP的区别(易混)浏览器

1、HTTP协议服务器

HTTP本质上是一种协议,全称是Hypertext Transfer Protocol,即超文本传输协议。从名字上能够看出该协议用于规定客户端与服务端之间的传输规则,所传输的内容不局限于文本(其实能够传输任意类型的数据)。微信

1053533-7152b9157998397d.png

图1.1传输示意图.pngcookie

2、HTTP请求与响应的内容网络

当咱们往服务端发送一条HTTP请求时都发送了哪些东西过去呢?多线程

先看一个POST请求的示例图:

1053533-b07ef5c0fd592270.png

图2.1 HTTP_POST请求示例.png

注:本文使用Paw来模拟发送HTTP请求,使用Charles抓包,Charles选中"Request"以及"Raw"选项就能够看到请求的所有内容

以上示例图中其实已经包含了一个HTTP请求所必备的几大要素:请求行、请求头(headerField)、请求体(body);同理,响应也有状态行、响应头、实体内容。接下来咱们逐个展开。

一、请求行

请求行包含请求方法(Method)、请求统一资源标识符(URI)、HTTP版本号,如图2.1第一行所示:

1053533-c94d968700d4b071.png

图2.2 请求行.png

  • 请求方法就是咱们所熟悉的POST、GET、HEAD、PUT等

  • URI就是URL中排除掉Host剩下的部分,也就是资源在服务器本地上的路径

  • HTTP版本号,目前主流的版本是1.1(1999年开始采用),最新的版本是2.0(2015年5月发布)。不一样版本之间差别下面会再展开

二、请求头

请求头主要存放对客户端想给服务端的附加信息,下图框框的部分就是请求头:

1053533-89b1fdadd8ebaee2.png

图2.3 请求头.png

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

  • Host: 目标服务器的网络地址

  • Accept: 让服务端知道客户端所能接收的数据类型,如text/html */*

  • Content-Type: body中的数据类型,如application/json; charset=UTF-8

  • Accept-Language: 客户端的语言环境,如zh-cn

  • Accept-Encoding: 客户端支持的数据压缩格式,如gzip

  • User-Agent: 客户端的软件环境,咱们能够更改该字段为本身客户端的名字,好比QQ music v1.11,好比浏览器Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Maxthon/4.5.2

  • Connection: keep-alive,该字段是从HTTP 1.1才开始有的,用来告诉服务端这是一个持久链接,“请服务端不要在发出响应后当即断开TCP链接”。关于该字段的更多解释将在后面的HTTP版本简介中展开。

  • Content-Length: body的长度,若是body为空则该字段值为0。该字段通常在POST请求中才会有。

POST请求的body请求体也有多是空的,所以POST中Content-Length也有可能为0

  • Cookie: 记录者用户信息的保存在本地的用户数据,若是有会被自动附上

值得一提的是,在iOS中当你发送一个任意请求时,无论你愿不肯意,NSURLRequest都会自动帮你记录你所访问的URL上设置的cookie。在iOS中用NSHTTPCookieStorage表示,是一个单例。经过

1

2

3

4

NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];

for (NSHTTPCookie *cookie in [cookieJar cookies]) {

 NSLog(@"%@", cookie);

}

能够获取目前被自动保存的全部cookie。对cookie的操做感兴趣的请移步iOS中http请求使用cookie这篇文章。

以上就是咱们平常开发中比较常常遇到的请求头,其实还有其余的field,但篇幅所限没法一一列出,想了解全部请求头请看这里请求头响应头列表。那在iOS中如何设置添加这些field呢?可使用-[NSMutableURLRequest addValue: forHTTPHeaderField:]方法,获取当前请求已经设置的field能够用-[NSURLRequest allHTTPHeaderFields]。也就是咱们能够经过以上接口定制咱们所须要的请求头,可是有些field是不能改的,咱们看一下iOS的描述:

1053533-79ae4585ef057a7d.png

图2.4 iOS请求头接口描述.png

从文档中咱们能够看到,在iOS中不该当对Authorization Connection Host WWW-Authenticate这几个header field作更改。

三、请求体

真正须要发给服务端的数据,在使用POST-multipart上传请求中请求体就是上传文件的二进制NSData类型数据;在GET请求中请求体为空;在普通的POST请求中请求体就是一些表单数据。在iOS中通常用NSURLRequest与NSMutableURLRequest的HTTPBody属性表示,添加body用-[NSMutableURLRequest setHTTPBody:]。

四、响应状态行

状态行是服务端返回给客户端的状态信息,包含HTTP版本号、状态码、状态码对应的英文名称。

如下就是典型的正确状态行:

1

HTTP/1.1 200 OK

这个部分须要讲的是错误码。事实上HTTP请求错误码能够根据错误码从左往右第一个数字大体分为如下几类:

1XX:信息提示。不表明成功或者失败,表示临时响应,好比100表示继续,101表示切换协议

2XX: 成功

3XX: 重定向

4XX:客户端错误,颇有多是客户端发生问题,如亲切可爱的404表示未找到文件,说明你的URI是有问题的,服务器机子上该目录是没有该文件的;414URI太长

5XX: 服务器错误,好比504网关超时

错误码是不用去记的,出错了再查对应的错误码含义就行。可是知道上面的分类有助于第一时间作出大致的判断,起码你能清楚是服务端仍是客户端的缘由。

五、响应头与响应实体

这部分与请求部分差别不大,响应头的字field会有稍许不一样,响应头中的header field一样移步请求头响应头列表。

3、HTTP版本简介

这里我把HTTP版本简单分为三类:1.1以前,1.1,2.0,针对这三类作个主要差别的介绍:

HTTP 1.1以前

  • 不支持持久链接。一旦服务器对客户端发出响应就当即断开TCP链接

  • 无请求头跟响应头

  • 客户端的先后请求是同步的。下一个请求必须等上一个请求从服务端拿到响应后才能发出,有点相似多线程的同步机制。

HTTP 1.1(主流版本)

与1.1以前的版本相比,作了如下性能上的提高

  • 增长请求头跟响应头

  • 支持持久链接。客户端经过请求头中指定Connection为keep-alive告知服务端不要在完成响应后当即释放链接。HTTP是基于TCP的,在HTTP 1.1中一次TCP链接能够处理屡次HTTP请求

  • 客户端不一样请求之间是异步的。下一个请求没必要等到上一个请求回来后再发出,而能够连续发出请求,有点相似多线程的异步处理。

HTTP 2.0

本着向下兼容的原则,1.1版本有的特性2.0都具有,也使用相同的API。可是2.0将只用于https网址。因为2.0的普及还须要比较长的一段时间,这里不展开,更多新特性请参考这篇文章

咱们重点关注一下当前1.1版本所作几点改变。支持持久链接有什么好处呢?HTTP是基于TCP链接的,若是链接被频繁地启动而后断开就会花费不少资源在TCP三次握手以及四次挥手上,效率低下。以请求一个网页为例,咱们知道,一个html网页上的图片资源并非直接嵌入在网页上,而只是提供url,图片仍须要额外发HTTP 请求去下载。一个网页从请求到最终加载到本地每每须要通过过个HTTP请求。在1.1版本以前请求一个网页就须要发生屡次"握手-挥手"的过程,每次链接之间相互独立;而1.1及以后的版本最少只须要一次就够。

再来就是请求异步,其好处参考多线程异步处理,在此不展开。

以上特性能够用图2.3表示:

1053533-2252667cc306fb0d.jpg

图3.1 异步请求.jpg

咱们能够看到:一、N次请求其实只创建了1次TCP链接,二、N次请求连续异步发出。

4、HTTP、Socket、TCP的区别

这三个概念常常被谈到,也是比较容易被混掉的概念。在回顾以前咱们先看一下这三者在TCP/IP协议族中的位置关系:

1053533-2139768be5c88e8b.png

图4.1 层次关系.png

HTTP是应用层的协议,更靠近用户端;TCP是传输层的协议;而socket是从传输层上抽象出来的一个抽象层,本质是接口。因此本质上三种仍是很好区分的。尽管如此,有时候你可能会懵逼,HTTP链接、TCP链接、socket链接有什么区别?好吧,若是上面的图解释的仍是不够清楚的话,咱们继续往下看。

一、TCP链接与HTTP链接的区别

上文提过,HTTP是基于TCP的,客户端往服务端发送一个HTTP请求时第一步就是要创建与服务端的TCP链接,也就是先三次握手,“你好,你好,你好”。从HTTP 1.1开始支持持久链接,也就是一次TCP链接能够发送屡次的HTTP请求。

小总结:HTTP基于TCP

二、TCP链接与Socket链接的区别

在图4.1中咱们提到,socket层只是在TCP/UDP传输层上作的一个抽象接口层,所以一个socket链接能够基于链接,也有可能基于UDP。基于TCP协议的socket链接一样须要经过三次握手创建链接,是可靠的;基于UDP协议的socket链接不须要创建链接的过程,不过对方能不能收到都会发送过去,是不可靠的,大多数的即时通信IM都是后者。

小总结:Socket也基于TCP

三、HTTP链接与Socket链接的区别

区分这两个概念是比较有意义的,毕竟TCP看不见摸不着,HTTP与Socket是实实在在能用到的。

  • HTTP是短链接,Socket(基于TCP协议的)是长链接。尽管HTTP1.1开始支持持久链接,但仍没法保证始终链接。而Socket链接一旦创建TCP三次握手,除非一方主动断开,不然链接状态一直保持。

  • HTTP链接服务端没法主动发消息,Socket链接双方请求的发送前后限制。这点就比较重要了,由于它将决定两者分别适合应用在什么场景下。HTTP采用“请求-响应”机制,在客户端还没发送消息给服务端前,服务端没法推送消息给客户端。必须知足客户端发送消息在前,服务端回复在后。Socket链接双方相似peer2peer的关系,一方随时能够向另外一方喊话。

四、问题来了:何时该用HTTP,何时该用socket

这个问题的提出是很天然而然的。当你接到一个与另外一方的网络通信需求,天然会考虑用HTTP仍是用Socket。

  • 用HTTP的状况:双方不须要时刻保持链接在线,好比客户端资源的获取、文件上传等。

  • 用Socket的状况:大部分即时通信应用(QQ、微信)、聊天室、苹果APNs等

在iOS中,发HTTP请求通常用原生的NSURLConnection、NSURLSession或者开源的AFNetWorking(推荐)、ASIHttpRequest(已中止更新)。链接Socket链接我用的比较可能是robbiehanson大神的CocoaAsyncSocket(XMPPFramework也是出自他手)。

5、The end

以上就是关于HTTP相关概念的回顾,适合菜鸟也适合有经验同窗一块儿回顾。

相关文章
相关标签/搜索