HTTP in iOS你看我就够
HTTP属于老话题了,在项目中我们经常需要往服务端发POST或者GET请求,但是对于HTTP的了解不应只局限于此。千里之行,始于足下。越想走的远,基本原理就应该了解的透彻全面一些,仅仅停留在使用ASIHttpRequest或者AFNetWorking传个参数发个请求的程度上是不够的。这篇文章就是带你全方面回顾一下HTTP。
通过本文你能收获哪些内容:
·完整HTTP请求与响应包含的必要元素
·HTTP不同版本之间的差异
·HTTP、Socket、TCP的区别(易混)
一、HTTP协议
HTTP本质上是一种协议,全称是Hypertext Transfer Protocol,即超文本传输协议。从名字上可以看出该协议用于规定客户端与服务端之间的传输规则,所传输的内容不局限于文本(其实可以传输任意类型的数据)。
图1.1传输示意图.png
二、HTTP请求与响应的内容
当我们往服务端发送一条HTTP请求时都发送了哪些东西过去呢?
先看一个POST请求的示例图:
图2.1 HTTP_POST请求示例.png
注:本文使用Paw来模拟发送HTTP请求,使用Charles抓包,Charles选中”Request”以及”Raw”选项就可以看到请求的全部内容
以上示例图中其实已经包含了一个HTTP请求所必备的几大要素:请求行、请求头(headerField)、请求体(body);同理,响应也有状态行、响应头、实体内容。接下来我们逐个展开。
1、请求行
请求行包含请求方法(Method)、请求统一资源标识符(URI)、HTTP版本号,如图2.1第一行所示:
图2.2 请求行.png
请求方法就是我们所熟悉的POST、GET、HEAD、PUT等
URI就是URL中排除掉Host剩下的部分,也就是资源在服务器本地上的路径
HTTP版本号,目前主流的版本是1.1(1999年开始采用),最新的版本是2.0(2015年5月发布)。不同版本之间差异下面会再展开
2、请求头
请求头主要存放对客户端想给服务端的附加信息,下图框框的部分就是请求头:
图2.3 请求头.png
HTTP请求在iOS中用NSURLRequest与NSMutableRequest表示;HTTP响应用NSHTTPURLResponse表示。
Host: 目标服务器的网络地址
Accept: 让服务端知道客户端所能接收的数据类型,如text/html */*
Content-Type: body中的数据类型,如application/json;
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表示,是一个单例。通过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的描述:
图2.4 iOS请求头接口描述.png
从文档中我们可以看到,在iOS中不应当对Authorization Connection Host WW
W-Authenticate这几个header field做更改。
3、请求体
真正需要发给服务端的数据,在使用POST-multipart上传请求中请求体就是上传文件的二进制NSData类型数据;在GET请求中请求体为空;在普通的POST请求中请求体就是一些表单数据。在iOS中一般用NSURLRequest与NSMutableURLRequest的HTTPBody属性表示,添加body用-[NSMutableURLRequest setHTTPBody:]。
4、响应状态行
状态行是服务端返回给客户端的状态信息,包含HTTP版本号、状态码、状态码对应的英文名称。
以下就是典型的正确状态行:
HTTP/1.1 200 OK
这个部分需要讲的是错误码。事实上HTTP请求错误码可以根据错误码从左往右第一个数字大致分为以下几类:
1XX:信息提示。不代表成功或者失败,表示临时响应,比如100表示继续,101表示切换协议
2XX: 成功
3XX: 重定向
4XX:客户端错误,很有可能是客户端发生问题,如亲切可爱的404表示未找到文件,说明你的URI是有问题的,服务器机子上该目录是没有该文件的;414URI太长
5XX: 服务器错误,比如504网关超时
错误码是不用去记的,出错了再查对应的错误码含义就行。但是知道上面的分类有助于第一时间做出大体的判断,起码你能清楚是服务端还是客户端的原因。
5、响应头与响应实体
这部分与请求部分差异不大,响应头的字field会有稍许不同,响应头中的header field同样移步请求头响应头列表。
三、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的普及还需要比较长的一段时间,这里不展开,更多新特性请参考这篇文章。
http://www.uiseo.cn/http-status-codes
我们重点关注一下当前1.1版本所做几点改变。支持持久连接有什么好处呢?HTTP是基于TCP连接的,如果连接被频繁地启动然后断开就会花费很多资源在TCP三次握手以及四次挥手上,效率低下。以请求一个网页为例,我们知道,一个html网页上的图片资源并不是直接嵌入在网页上,而只是提供url,图片仍需要额外发HTTP 请求去下载。一个网页从请求到最终加载到本地往往需要经过过个HTTP请求。在1.1版本之前请求一个网页就需要发生多次”握手-挥手”的过程,每次连接之间相互独立;而1.1及之后的版本最少只需要一次就够。
再来就是请求异步,其好处参考多线程异步处理,在此不展开。
以上特性可以用图2.3表示:
图3.1 异步请求.jpg
我们可以看到:1、N次请求其实只建立了1次TCP连接,2、N次请求连续异步发出。
四、HTTP、Socket、TCP的区别
这三个概念经常被谈到,也是比较容易被混掉的概念。在回顾之前我们先看一下这三者在TCP/IP协议族中的位置关系:
图4.1 层次关系.png
HTTP是应用层的协议,更靠近用户端;TCP是传输层的协议;而socket是从传输层上抽象出来的一个抽象层,本质是接口。所以本质上三种还是很好区分的。尽管如此,有时候你可能会懵逼,HTTP连接、TCP连接、socket连接有什么区别?好吧,如果上面的图解释的还是不够清楚的话,我们继续往下看。
1、TCP连接与HTTP连接的区别
上文提过,HTTP是基于TCP的,客户端往服务端发送一个HTTP请求时第一步就是要建立与服务端的TCP连接,也就是先三次握手,“你好,你好,你好”。从HTTP 1.1开始支持持久连接,也就是一次TCP连接可以发送多次的HTTP请求。
小总结:HTTP基于TCP
2、TCP连接与Socket连接的区别
在图4.1中我们提到,socket层只是在TCP/UDP传输层上做的一个抽象接口层,因此一个socket连接可以基于TCP,也有可能基于UDP。基于TCP协议的socket连接同样需要通过三次握手建立连接,是可靠的;基于UDP协议的socket连接不需要建立连接的过程,不过对方能不能收到都会发送过去,是不可靠的,大多数的即时通讯IM都是后者。
小总结:Socket也可以基于TCP
3、HTTP连接与Socket连接的区别
区分这两个概念是比较有意义的,毕竟TCP看不见摸不着,HTTP与Socket是实实在在能用到的。
HTTP是短连接,Socket(基于TCP协议的)是长连接。尽管HTTP1.1开始支持持久连接,但仍无法保证始终连接。而Socket连接一旦建立TCP三次握手,除非一方主动断开,否则连接状态一直保持。
HTTP连接服务端无法主动发消息,Socket连接双方请求的发送先后限制。这点就比较重要了,因为它将决定二者分别适合应用在什么场景下。HTTP采用“请求-响应”机制,在客户端还没发送消息给服务端前,服务端无法推送消息给客户端。必须满足客户端发送消息在前,服务端回复在后。Socket连接双方类似peer2peer的关系,一方随时可以向另一方喊话。
4、问题来了:什么时候该用HTTP,什么时候该用socket
这个问题的提出是很自然而然的。当你接到一个与另一方的网络通讯需求,自然会考虑用HTTP还是用Socket。
用HTTP的情况:双方不需要时刻保持连接在线,比如客户端资源的获取、文件上传等
用Socket的情况:大部分即时通讯应用(QQ、微信)、聊天室、苹果APNs等
在iOS中,发HTTP请求一般用原生的NSURLConnection、NSURLSession或者开源的AFNetWorking(推荐)、ASIHttpRequest(已停止更新)。连接Socket连接我用的比较多是robbiehanson大神的CocoaAsyncSocket (XMPPFramework也是出自他手)。
五、The end
以上就是关于HTTP相关概念的回顾,适合菜鸟也适合有经验同学一起回顾。
欢迎留言,如果写的不对的地方还请不吝指出。
HTTP in iOS你看我就够的更多相关文章
- 【原】HTTP in iOS你看我就够
声明:本文是本人 编程小翁 原创,转载请注明. 本文同步发布在简书中,强烈建议移步简书查看,编程小翁 HTTP属于老话题了,在项目中我们经常需要往服务端发POST或者GET请求,但是对于HTTP的了解 ...
- 学习ios(必看经典)牛人40天精通iOS开发的学习方法
学习ios(必看经典)牛人40天精通iOS开发的学习方法 描述 这是一套从一个对iOS开发感兴趣的学员到iOS开发高手的系统.专业的课程体系.以培养企业开发真正需要的人才为目标,每个知识点都用案例来讲 ...
- 【转】 学习ios(必看经典)牛人40天精通iOS开发的学习方法【2015.12.2
原文网址:http://bbs.51cto.com/thread-1099956-1.html 亲爱的学员们: 如今,各路开发者为淘一桶金也纷纷转入iOS开发的行列.你心动了吗?想要行动吗?知道如何做 ...
- iOS 仿看了吗应用、指南针测网速等常用工具、自定义弹出视图框架、图片裁剪、内容扩展等源码
iOS精选源码 扩展内容的cell - folding-cell 一个近乎完整的可识别中国身份证信息的Demo 可自动快速... JPImageresizerView 仿微信的图片裁剪 带年月和至今以 ...
- 关于iOS多线程,你看我就够了
在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项.当然也会给出几种多线程的案例,在实际使用中感受它们的区别.还有一点需要说明的是,这篇文章将会使 用 Swift ...
- iOS 去除警告 看我就够了
你是不是看着开发过程中出现的一堆的警告会心情一阵烦躁,别烦躁了,看完此文章,消除警告的小尾巴. 一.SVN 操作导致的警告 1.svn删除文件后报错 ”xx“is missing from worki ...
- iOS 数据库sqlite3.0操作--超简单--看我就够啦
iOS客户端数据存储的方式有很多,下面主要是介绍苹果自带的sqlite3.0的使用方法. 首先导入sqlite3.0的框架.然后导入头文件#import <sqlite3.h>就行了 下面 ...
- iOS本地数据存取,看这里就够了
本文授权转载,作者:hosea_zhou(简书) 应用沙盒 1)每个iOS应用都有自己的应用沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离.应用必须待在自己的沙盒里,其他应用不能访问该沙盒 2) ...
- iOS之3DTouch的使用---很简单,看我就够啦~~
3DTouch是苹果在iOS9之后新推出的功能,功能大致可以分成两种,一种是长按app的icon,会出现以下的界面,还有一种是在app内部的某个视图上使用,效果如下图. 详细的效果也可以参见微信.微信 ...
随机推荐
- <和>
今天用到>查了查资料就是这么个回事.
- nginx 编译选项
内容有些多,一眼看来难免头昏脑胀,但坚持看完,相信你一定会有所收获. nginx参数: --prefix= 指向安装目录 --sbin-path 指向(执行)程序文件(nginx) --conf-pa ...
- 提高Order by语句查询效率的两个思路
提高Order by语句查询效率的两个思路 2011-03-01 13:07 水太深 ITPUB 字号:T | T 在MySQL数据库中,Order by语句的使用频率是比较高的.但是众所周知,在使用 ...
- python 性能鸡汤
转载自:http://www.oschina.net/question/1579_45822 1:使用内建函数input() int() isinstance() issubclass() iter( ...
- Dungeon Master(poj 2251)
Description You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is co ...
- 用它解决大问题啦,STRACE应用
脚本是沙沙,辉哥和我在去年解决一个PHP时弄出来的...强! 简单而实用. 抓到的TRC文件放在TRC目录下. 如果有异常的进程或输出,可以在里面详细的分析.. #!/bin/bash mkdir t ...
- Shredding Company(dfs)
Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 3519 Accepted: 2009 Description You h ...
- CH Round #52 - Thinking Bear #1 (NOIP模拟赛)
A.拆地毯 题目:http://www.contesthunter.org/contest/CH%20Round%20%2352%20-%20Thinking%20Bear%20%231%20(NOI ...
- Linux后台进程管理的一些命令小结
Linux后台进程管理的一些命令:fg.bg.jobs.&.ctrl + z命令,供大家学习参考 一. &加在一个命令的最后,可以把这个命令放到后台执行 ,如gftp &, ...
- 【Gzip】
为你的网站开启 gzip 压缩功能(nodejs.nginx) Do not forget to use Gzip for Express.js 网页GZIP压缩检测