iOS | HTTP介绍 & TCP/UDP & DNS
一、什么是HTTP协议 ?
HTTP
本质上是一种协议,全称是Hypertext Transfer Protocol
,即超文本传输协议
。HTTP
是一个基于TCP/IP
通信协议来传递数据, 从名字上可以看出该协议用于规定客户端与服务端之间的传输规则,所传输的内容不局限于文本(其实可以传输任意类型的数据)。
二、HTTP请求/响应报文
当我们往服务端发送一条HTTP请求时都发送了哪些东西过去呢?先看一个POST请求的示例图:
image.png
以上示例图中其实已经包含了一个HTTP请求所必备的几大要素:
请求行、请求头(headerField)、请求体(body);同理,响应也有状态行、响应头、实体内容。
下图给出了请求报文的一般格式。
image.png
2.1 请求行
请求行包含请求方法(Method)、请求统一资源标识符(URI)、HTTP版本号
image.png
- 请求方法就是我们所熟悉的POST、GET、HEAD、PUT等
- URI就是URL中排除掉Host剩下的部分,也就是资源在服务器本地上的路径
- HTTP版本号,目前主流的版本是1.1(1999年开始采用),最新的版本是2.0(2015年5月发布)。
2.2 请求头
请求头主要存放对客户端想给服务端的附加信息下, 如下图所示
image.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请求中才会有。
- Cookie: 记录者用户信息的保存在本地的用户数据,如果有会被自动附上
值得一提的是,在iOS中当你发送一个任意请求时,不管你愿不愿意,NSURLRequest都会自动帮你记录你所访问的URL上设置的cookie。在iOS中用NSHTTPCookieStorage表示,是一个单例。通过
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
NSLog(@"%@", cookie);
}
以上就是我们日常开发中比较经常遇到的请求头,其实还有其他的field。那在iOS中如何设置添加这些field呢?可以使用-[NSMutableURLRequest addValue: forHTTPHeaderField:]
方法,获取当前请求已经设置的field可以用-[NSURLRequest allHTTPHeaderFields]
。也就是我们可以通过以上接口定制我们所需要的请求头,但是有些field是不能改的
2.3、请求体
真正需要发给服务端的数据,在使用POST-multipart上传请求中请求体就是上传文件的二进制NSData类型数据;在GET请求中请求体为空;在普通的POST请求中请求体就是一些表单数据。在iOS中一般用NSURLRequest
与NSMutableURLRequest
的HTTPBody
属性表示,添加body用-[NSMutableURLRequest setHTTPBody:]
。
2.4、响应行
状态行是服务端返回给客户端的状态信息,包含HTTP版本号、状态码、状态码对应的英文名称。
以下就是典型的正确状态行:
HTTP/1.1 200 OK
这个部分需要讲的是错误码。事实上HTTP请求错误码可以根据错误码从左往右第一个数字大致分为以下几类:
1XX:信息提示。不代表成功或者失败,表示临时响应,比如100表示继续,101表示切换协议
2XX: 成功
3XX: 重定向
4XX:客户端错误,很有可能是客户端发生问题,如亲切可爱的404
表示未找到文件,说明你的URI是有问题的,服务器机子上该目录是没有该文件的;414
URI太长
5XX: 服务器错误,比如504
网关超时
HTTP状态码详细列表: http://www.runoob.com/http/http-status-codes.html
2.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的普及还需要比较长的一段时间,这里不展开
我们重点关注一下当前1.1版本所做几点改变。支持持久连接有什么好处呢?
HTTP是基于TCP连接的,如果连接被频繁地启动然后断开就会花费很多资源在TCP三次握手以及四次挥手上,效率低下。以请求一个网页为例,我们知道,一个html网页上的图片资源并不是直接嵌入在网页上,而只是提供url,图片仍需要额外发HTTP 请求去下载。一个网页从请求到最终加载到本地往往需要经过过个HTTP请求。在1.1版本之前请求一个网页就需要发生多次"握手-挥手"的过程,每次连接之间相互独立;而1.1及之后的版本最少只需要一次就够。
再来就是请求异步,其好处参考多线程异步处理,在此不展开。
以上特性可以用图2.3表示:
image.png我们可以看到:1、N次请求其实只建立了1次TCP连接,2、N次请求连续异步发出。
四 、HTTP协议特点
HTTP 是一个属于应用层的面向对象的协议,HTTP 协议一共有五大特点:1、支持客户/服务器模式;2、简单快速;3、灵活;4、无连接;5、无状态
。
- 支持客户/服务器模式。
- 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
- 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type(Content-Type是HTTP包中用来表示内容类型的标识)加以标记。
- 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
五、HTTP建立过程
- 首先需要进行 Tcp 的三次握手
- HTTP 的请求/响应过程
- Tcp 四次挥手连接释放
如下图所示:
image.png
五、HTTP、Socket、TCP的区别
这三个概念经常被谈到,也是比较容易被混掉的概念。在回顾之前我们先看一下这三者在TCP/IP协议族中的位置关系:
image.pngHTTP是应用层的协议,更靠近用户端;TCP是传输层的协议;而socket是从传输层上抽象出来的一个抽象层,本质是接口。所以本质上三种还是很好区分的。尽管如此,有时候你可能会懵逼,HTTP连接、TCP连接、socket连接有什么区别?好吧,如果上面的图解释的还是不够清楚的话,我们继续往下看。
4.1 TCP连接与HTTP连接的区别
上文提过,HTTP是基于TCP的,客户端往服务端发送一个HTTP请求时第一步就是要建立与服务端的TCP连接,也就是先三次握手,“你好,你好,你好”。从HTTP 1.1开始支持持久连接,也就是一次TCP连接可以发送多次的HTTP请求。
小总结:HTTP基于TCP
4.2、TCP连接与Socket连接的区别
在图4.1中我们提到,socket层只是在TCP/UDP传输层上做的一个抽象接口层,因此一个socket连接可以基于TCP,也有可能基于UDP。基于TCP协议的socket连接同样需要通过三次握手建立连接,是可靠的;基于UDP协议的socket连接不需要建立连接的过程,不过对方能不能收到都会发送过去,是不可靠的,大多数的即时通讯IM都是后者。
小总结:Socket也可以基于TCP
4.3、HTTP连接与Socket连接的区别
区分这两个概念是比较有意义的,毕竟TCP看不见摸不着,HTTP与Socket是实实在在能用到的。
- HTTP是短连接,Socket(基于TCP协议的)是长连接。尽管HTTP1.1开始支持持久连接,但仍无法保证始终连接。而Socket连接一旦建立TCP三次握手,除非一方主动断开,否则连接状态一直保持。
- HTTP连接服务端无法主动发消息,Socket连接双方请求的发送先后限制。这点就比较重要了,因为它将决定二者分别适合应用在什么场景下。HTTP采用“请求-响应”机制,在客户端还没发送消息给服务端前,服务端无法推送消息给客户端。必须满足客户端发送消息在前,服务端回复在后。Socket连接双方类似peer2peer的关系,一方随时可以向另一方喊话。
4.4、问题来了:什么时候该用HTTP,什么时候该用socket
这个问题的提出是很自然而然的。当你接到一个与另一方的网络通讯需求,自然会考虑用HTTP还是用Socket。
- 用HTTP的情况:双方不需要时刻保持连接在线,比如客户端资源的获取、文件上传等
- 用Socket的情况:大部分即时通讯应用(QQ、微信)、聊天室、苹果APNs等
在iOS中,发HTTP请求一般用原生的NSURLConnection
、NSURLSession
或者开源的AFNetWorking(推荐)
、ASIHttpRequest(已停止更新)
。连接Socket连接我用的比较多是robbiehanson大神的[CocoaAsyncSocket] (XMPPFramework
也是出自他手)。
六. TCP/UDP
TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)协议属于传输层协议。其中TCP提供IP环境下的数据可靠传输,它提供的服务包括数据流传送、可靠性、有效流控、全双工操作和多路复用。通过面向连接、端到端和可靠的数据包发送。而UDP则不为IP提供可靠性、流控或差错恢复功能。一般来说,TCP对应的是可靠性要求高的应用,而UDP对应的则是可靠性要求低、传输经济的应用。
6.1 TCP
TCP(传输控制协议)
是基于连接的协议,是面向连接的, 也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来经过三次“对话”之后,主机A才向主机B正式发送数据。
TCP协议能为应用程序提供可靠的通信连接,使一台计算机发出的字节流无差错地发往网络上的其他计算机,对可靠性要求高的数据通信系统]往往使用TCP协议传输数据。
6.2 UDP
UDP(用户数据报协议)
是与TCP相对应的协议。它是面向非连接
的协议,它不与对方建立连接,而是直接就把数据包
发送过去!UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境可以使用UDP
6.3 TCP/ UDP区别
- TCP面向连接(三次握手);UDP是无连接的,即发送数据之前不需要建立连接
- TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付, Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
- UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
- 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
- TCP对系统资源要求较多,UDP对系统资源要求较少。
七. DNS
域名系统(DomainNameSystem,缩写:DNS)是[互联网]的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问[互联网], 工作原理如下图:
image.pngDNS解析查询方式
-
(1)递归查询
递归查询是一种DNS 服务器的查询模式,在该模式下DNS 服务器接收到客户机请求,必须使用一个准确的查询结果回复客户机。如果DNS 服务器本地没有存储查询DNS 信息,那么本地服务器就会成为DNS中的一台客户机,并向上级域名服务器发出查询请求,这种过程将持续到找到具有相关信息的域名服务器为止,然后将返回的查询结果提交给客户机。
过程中如果没有找到查询结果,重复递归上述操作直至根域名服务器,根域名服务器收到DNS请求后,把所查询得到的所请求的DNS域名中发送给顶级域名服务器,让顶级域名服务器去往下级域名服务器请求查找,如果找到了就原路返回。某域名服务器-->...->顶级域名服务器-->根域名服务器-->下一级域名服务器-->...-->本地域名服务器-->客户机。如果没有找到就报错,表示无法查询到相关信息;
image.png
-
(2)迭代查询
DNS 服务器另外一种查询方式为迭代查询,DNS 服务器会向客户机提供其他能够解析查询请求的DNS 服务器地址,当客户机发送查询请求时,DNS 服务器并不直接回复查询结果,而是告诉客户机另一台DNS 服务器地址,客户机再向这台DNS 服务器提交请求,依次循环直到返回查询的结果为止。
image.png
DNS劫持问题
DNS劫持又称(域名劫持
), 是指在劫持的网络范围内拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行,否则返回假的IP地址或者什么都不做使请求失去响应,其效果就是对特定的网络不能访问或访问的是假网址。
DNS劫持问题解决方案:
-
HTTPDNS
HTTPDNS 利用 HTTP 协议与 DNS 服务器交互,代替了传统的基于 UDP 协议的 DNS 交互,绕开了运营商的 Local DNS,有效防止了域名劫持,提高域名解析效率。
image.png
参考链接:
http://www.runoob.com/http/http-tutorial.html
https://www.cnblogs.com/xuxinstyle/p/9813654.html
https://blog.csdn.net/qq_34115899/article/details/82981007