iOS中网络相关内容
声明:部分图片来源于网络,有些内容也来自各个平台老师讲解的视频,部分内容来自《计算机网络》这本书中,除去参考其他博客链接外,其他部分不作出参考链接来源展示,如有相关原创博客有雷同,联系我附上出处链接,尊重原创作品,本博文不作商业用途,只是加上自己的理解总结大神们的精华,便于广大的开发者查找
整体目录
- 网络中的7层模型
- 应用层的HTTP、HTTPS
- 对称加密,非对称加密,混合加密
- HTTPS建立连接流程
- 网络层中的IP协议IP数据报首部概述
- 传输层中的TCP与UDP协议
- DNS解析
- TCP三次握手与四次挥手
- TCP流量控制,拥塞控制,可靠传输
- 结束语
1. 网络中的7层模型
在计算机网络中,我们把对网络七层协议从上到下,分别定义为:
- 应用层: 为操作系统或网络应用程序提供访问网络服务的接口,例如我们常见的:TeInte、FTP、HTTP、SNMP、DNS等
- 表示层:解密与加密,图片解码与编码,数据的压缩与解压缩,例如我们常见的有:URL加密、口令加密、图片编解码等
- 会话层:主要是使用校验点使会话在通信是小时从校验点恢复通信,例如:服务器验证用户登录、断点续传
- 传输层:建立连接,处理数据包错误,数据包次序,例如:TCP、UDP、SPX
- 网络层:对子网间的数据包进行路由选择,例如路由器、多层交换机、防火墙,IP协议
- 链路层:将数据分帧、物理地址寻址,例如:网卡,网桥,二层交换机等
- 物理层:传输介质 例如网线等
那么对于我们客户端的同学,其实网络大概分为3层就足够我们去研究,分别为应用层、传输层、网络层
,所以,在这里着重的展开对这四个层定义的概述:
应用层(Application Layer):
(象征性的说一些没用的屁话)主要负责对软件提供接口以使程序能使用网络服务。术语“应用层”并不是指运行在网络上的某个特别应用程序 ,应用层提供的服务包括文件传输、文件管理以及电子邮件的信息处理。
常见的协议:HTTP
、FTP
、HTTPS
、DNS
以下篇章里着重介绍HTTP,HTTPS
传输层(Transport Layer)
定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。 主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层数据叫做段。
在以下篇章里讲述UDP差错校验已经TCP差错校验与流量控制
网络层(Network Layer)
网络层通过综合考虑发送优先权、网络拥塞程度、服务质量以及可选路由的花费来决定从一个网络中节点A 到另一个网络中节点B 的最佳路径。由于网络层处理,并智能指导数据传送,路由器连接网络各段,所以路由器属于网络层。在网络中,“路由”是基于编址方案、使用模式以及可达性来指引数据的发送。
以下篇章终点阐述:IP协议
2.应用层的HTTP、HTTPS、DNS解析
HTTP协议概念
阐述HTTP的概念,大致目录为:
- HTTP基本概念
- HTTP请求方式
- HTTP特点
超文本传输协议,HTTP是基于TCP的应用层协议
请求报文与响应报文:
请求报文:
GET /8qUJcD3n0sgCo2Kml5_Y_D3/v.gif?pid=201&pj=www&fm=behs&qid=81f0291600046ade&tab=indexHot&path=https%3A%2F%2Fwww.baidu.com%2F&wd=&rsv_sid=31658_1445_31671_21080_31591_31605_31464_31715_30823&rsv_did=22f98012412ca12cf10abc42251952bc&t=1590563319831 HTTP/1.1
Host: sp1.baidu.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
//以上是首部行
(此处必须有一空行) //空行分割header和请求内容
name=world 请求体
- Host:指明了该对象所在的主机
- Content-Type:首部行用来表明 HTTP会将请求参数用key1=val1&key2=val2的方式进行组织,并放到请求实体里面
- Connection:告诉服务端使用持久连接
- User-agent:首部行用来指明用户代理,即向服务器发送请求的浏览器类型
- Accept-Language:首部行表示用户想得到该对象的法语版本(如果服务器中有这样的对象的话),否则,服务器应发送它的默认版本
响应报文:
HTTP/1.1 200 OK
//以上是状态行:协议版本字段、状态码、相应状态信息
Connection:close
Server:Apache/2.2.3(CentOS)
Date: Mon, 5 Dec 2020 23:59:59 GMT
Content-Type: text/html
Content-Length: 103
//以上是首部行
(此处必须有一空行) //空行分割header和实体主体
(data data data data)//响应实体主体
- Connection:close首部行告诉客户,发送完报文后将关闭TCP连接。
- Server:首部行指示该报文是由一台Apache Web服务器产生的,类似于HTTP请求报文里的User-agent
- Date:指的不是对象创建或最后修改的时间,而是服务器从文件系统中检索到该对象,插入到响应报文,并发送该响应报文的时间。
- Content-Type:部行指示了实体体中的对象是HTML文本
- Content-Length:首部行指示了被发送对象中的字节数
一些常见的状态码:
状态码 | 含义 |
---|---|
200 | 请求成功,返回数据在请求响应报文中 |
301 | 请求发生了重定向,拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取 |
400 | 客户端请求错误,服务无法识别该请求 |
404 | 被请求的文件不在该服务器 |
5XX | 与服务器相关的问题 |
一般以4开头的状态码,几乎都与客户端相关,以5开头的代码,几乎都与服务器相关
HTTP协议请求方式
GET、POST、PUT、DELETE、HEAD、OPTIONS
这里重点说明GET
与POST
请求
GET
首先GET请求是:安全的
幂等的
可缓存的
安全
:这里的安全是指不应引起Server端的任何状态变化
幂等
:同一个请求方法执行多次和执行一次的效果完全相同
可缓存
:请求是否可以被缓存,GET请求会主动进行Cache
- GET的请求参数一般以?分割拼接到URL后面
- GET参数长度限制为2048个字符
- GET请求由于参数裸露在URL中, 是不安全的(这里的不安全是指在外界通过外部很容易就能能获取到参数,并非语义上的安全的概念)
POST
首先POST请求是:非安全的
非幂等的
不可缓存的
非安全
:可能会引起服务器状态变化的,即是不安全的
非幂等
:同一个请求方法执行多次和执行一次的效果可能不相同,例如执行删除等等的操作
可缓存
:POST请求不可缓存
GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。
在响应时,GET产生一个TCP数据包;POST产生两个TCP数据包:对于GET方式的请求,浏览器会把Header和实体主体一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送Header,服务器响应100 Continue,浏览器再发送实体主体,服务器响应200 OK(返回数据)。
这里并不是说POST请求就一定要比GET请求要好,是要看具体的需求而定,如果是只读显示类的需求,还是优先使用GET请求,减少传输过程中额外个开销,同事由于可以缓存,所以会大大减少服务器的开销
HTTP特点
无状态
、无连接
无状态
:即协议对于事务处理没有记忆能力。
每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求时无直接关系的,它不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况
也就是说服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器
标准的HTTP协议指的是不包括cookies,session,application的HTTP协议
无连接
:即当本次请求完成结束后,就会断开连接,也就是说每个连接处理一个请求。想要一个连接可以处理多个请求,那么我们就需要保持持久力连接
如果想要保持持久连接,那么需要加上Cookie/Session的辅助。持久连接情况下,服务器发出响应后让TCP连接继续打开着。同一对客户/服务器之间的后续请求和响应可以通过这个连接发送。
对于非持久连接,TCP得在客户端和服务端分配TCP缓冲区,并维持TCP变量,会严重增加服务器负担。因为TCP有流量控制,后续会讲到,会增加每次请求的等待时长
那么在网络请求过程中,我们是怎么判断一个HTTP请求结束的呢?在这里引用慕课网有关讲解HTTP的一些方法:(不建议大家去听该老师,看看课件就行了,在这里只是标明原创的出处)
- 根据所接收字节数是否达到
Content-length
值 - 当选择分块传输时
chunked
,响应头中可以不包含Content-Length
,服务器会先回复一个不带数据的报文(只有响应行和响应头和\r\n),然后开始传输若干个数据块。当传输完若干个数据块后,需要再传输一个空的数据块,当客户端收到空的数据块时,则客户端知道数据接收完毕。
HTTPS协议
首先我们用一张图来对比HTTP与HTTPS
HTTP:
HTTPS:
HTTPS基于HTTP协议,通过SSL或TLS提供加密处理数据、验证对方身份以及数据完整性保护,也可以理解为HTTPS = HTTP + SSL/TLS协议
SSL
:全称是Secure Sockets Layer,即安全套接层协议,是为网络通信提供安全及数据完整性的一种安全协议。
TLS
:的全称是Transport Layer Security,即安全传输层协议。
3. 对称加密、非对称加密、混合加密
我们想要了解HTTP/HTTPS传输过程,就不得不先了解这些加密的含义
对称加密
:
对称加密,顾名思义,加密方与解密方使用同一钥匙(秘钥)。具体一些就是,发送方通过使用相应的加密算法和秘钥,对将要发送的信息进行加密;对于接收方而言,使用解密算法和相同的秘钥解锁信息,从而有能力阅读信息。
常见的算法有:DES、3DES、Blowfish…
非对称加密
在对称加密中,发送方与接收方使用相同的秘钥。那么在非对称加密中则是发送方与接收方使用的不同的秘钥。其主要解决的问题是 防止在秘钥协商的过程中发生泄漏。比如在对称加密中,假如一个渣男和情妇打电话说今晚去哪里哪里约会,顺便将房号以对称加密的方式发送到对方手机,而不巧的是渣男老婆雇了私人侦探窃取到了这个公共秘钥,这样很容易发生不愉快的事情,那么如果渣男以情妇的公钥加密发送短信,即使侦探拿到公钥后,因为没有情妇的私钥,也无法解密相关房号信息…
公钥算法:RSA等:
混合加密
为什么要使用混合加密呢,首先,非对称加密的解密过程是一个相当耗时打的操作,如果发送的信息很长,那么解密时需要消耗大量的时间,渣男情妇等不了啊…那么急于这么一个原因,就有人研究出混合加密算法,发短信的信息可以使用对称加密,将对称加密的秘钥进行非对称加密,也就是说,非对称加密的内容其实是对称加密的秘钥,也就是一串数字,即实现了防止在传输中途被窃取,又解决了解密时间长的问题
图中的会话秘钥:通过随机数加对称加密算法生成,可以简单的理解为对称加密秘钥
指纹
在这里,我也提一下与数字签名有关的东西,首先我们要知道单向散列函数
单向散列函数(哈希函数)
:在这里我只是简单的介绍一下,不展开叙述,单向散列函数可以根据任意长度的消息,计算出固定长度的散列值,这个计算过程速度很快,散列函数输出的散列值通常又被成作为指纹
,消息不同,散列值就不同,而且,根据散列值,无法确定出原来的消息是什么,称为不可逆,所以,散列函数是单向的
常见的单向散列函数算法有:MD5
、SHA1
、SHA2
…
那么这个数字签名是干什么用的呢?其实很好理解,不要和我们对称加密,非对称加密,混合加密混到一块,我们可以试想这么一个场景:
Bob突然接收到Alice发送的一段消息,解密后就裂开了,打电话找Alice理论,Alice很委屈,说不是他发送的,那么为了证明是不是Alice发送的,就需要用到单向散列函数,对Alice发送的消息进行指纹的输出,生成一个数字指纹,那么当Bob接收到这段消息的明文时候,可以再次利用单向散列函数进行散列值的输出,然后对比两个指纹,一样的话,没毛病,就是Alice发的,友谊的小船说翻就翻,不一样的话,证明确实不是Alice发的,是别人伪装的.
数字签名
数字签名基于指纹加上非对称加密实现的传输过程,废话不多说,直接上图
首先
- 在图中没有反映,就是Alice要生成自己的公私钥,将公钥给Bob
- Alice用单向散列函数进行散列值输出
- Alice用自己的私钥对散列值(指纹进行)加密,这一步叫做签名
- 利用混合加密的方式发送消息的同时,将自己私钥加密后的签名发送给Bob
- Bob通过自己的私钥解密Alice发送过来的消息,用同样的单向散列函数对Alice发送过来的消息进行散列值输出
- Bob同时用Alice的公钥对Alice的签名进行解密
- 将这两个散列值进行对比
敲黑板!!!!:这里同时也为iOS端App数字签名的原理,也就是你从Appstore官网上下载的证书,打包签名一系列的流程,在这里都是这个原理,这里考虑到篇幅,不在过多赘述
总结下数字签名的作用:
- 可以保证数据的完整性
- 防止别人篡改消息
- 防止别人否认自己发送的消息
4.HTTPS建立连接流程
此段原文出处:(点我看原文(其实原文也是对慕课网网络这节课的总结))
在HTTP中,也同时使用了混合加密的方式进行加密
- 服务端生成的
私钥
和公钥
,用来非对称加密 - 客户端生成临时的
会话秘钥
,用来进行对称加密
过程:
- 客户端访问HTTPS连接
客户端会把安全协议版本号
、客户端支持的加密算法列表
、随机数C
发给服务端。 - 服务端发送证书给客户端
服务端接收密钥算法配件后,会和自己支持的加密算法列表进行比对,如果不符合,则断开连接。否则,服务端会在该算法列表中,选择一种对称算法(如AES
)、一种公钥算法
(如具有特定秘钥长度的RSA)和一种MAC
算法发给客户端。服务器端有一个密钥对,即公钥
和私钥
,是用来进行非对称加密使用的,服务器端保存着私钥
,不能将其泄露,公钥
可以发送给任何人。
在发送加密算法的同时还会把数字证书
和随机数S
发送给客户端 - 客户端验证server证书
会对server公钥进行检查,验证其合法性,如果发现发现公钥有问题,那么HTTPS传输就无法继续。验证方式为上面提到的指纹认证 - 客户端组装会话秘钥
如果公钥
合格,那么客户端会用服务器公钥来生成一个前主秘钥(Pre-Master Secret,PMS)
,并通过该前主秘钥和随机数C
、S
来组装成会话秘钥
- 客户端将前主秘钥加密发送给服务端
是通过服务端的公钥
来对前主秘钥
进行非对称加密
,发送给服务端 - 服务端通过私钥解密得到前主秘钥
服务端接收到加密信息后,用私钥解密
得到主秘钥
。 - 服务端组装会话秘钥
服务端通过前主秘钥
和随机数C
、S
来组装会话秘钥。
至此,服务端和客户端都已经知道了用于此次会话的主秘钥
。 - 数据传输
客户端收到服务器发送来的密文,用客户端密钥对其进行对称解密,得到服务器发送的数据。
同理,服务端收到客户端发送来的密文,用服务端密钥对其进行对称解密,得到客户端发送的数据。
会话秘钥
= random S
+ random C
+ 前主秘钥
5. 网络层中的IP协议
我在写这篇博文的时候顺序调整了很久,最后将IP协议调整到了第四部分,因为,想要了解构建请求过程,就必须了解TCP协议,要想了解TCP协议,就涉及到TCP协议的差错校验已经流量控制来保证可靠传输,有序传输,要想了解TCP的可靠传输与有序传输,那我们必须了解IP协议的无序性,这样才有对比
IP协议的数据报格式(IPV4为例)
- 版本号:占四位,就是IP协议的版本,通信双方的IP协议必须要达到一致,IPv4的版本就是4
- 首部长度:占四位,因为长度为四比特,所以首部长度的最大值为1111,15,又因为首部长度代表的单位长度为32个字(也就是4个字节),所以首部长度的最小值就是0101,当然,也确实如此,大部分的ip头部中首部字节都是0101.也就是5*4=20个字节,如果是最大值15的话,ip首部的最大值就是60个字节,所以记好了,ipv4首部长度的最大值就是60,当然当中我们又能发现,IPv4的首段长度一定是4字节的整数倍,要是不是怎么办呢?别急,后面的填充字段会自动填充补齐到4字节的整数倍的。
- 这个没有什么用处,也没有什么好讲的了,只要自动这玩意占八位,一个字节就可以了
- 总长度:占16位,这个的意思就是ip数据报中首部和数据的总和的长度,因为占16位,所以很好理解,总长度的最大值就是2的16次方减一,65535,这玩意也对应着还有一个很简单的概念,最大传输单元mtu,意味着一个IP数据报的最大长度就只能装下65535个字节,要是传输的长度超过这个怎么办,很简单,分片。
- 位标识(id):占16位 唯一的标识主机发送的报文. 如果IP报文在数据链路层被分片了, 那么每一个片里面的这个id是相同的
- 3位标志位:第一位保留,第二位置为1表示禁止分片, 这时候如果报文长度超MTU, IP模块就会丢弃报文. 第三位表示”更多分片”, 如果分片了的话, 最后一个分片置为1, 其他是0
- 片偏移:占13位,是分片相对于原始IP报文开始处的偏移. 其实就是在表示当前分片在原报文中处在哪个位置
- 生存时间(TTL):数据报到达目的地的最大报文跳数
- 协议类型:占8位,表示上层协议的类型
- 校验和:占16位重点
首部检验和
我们要说一下
过程为
- 发送数据报时首先将ip首部的校验和全部置为0,然后,以16位为单位,全部相加,如果有进位,那么加到第四位,然后将加起来的和取按位反码得到校验和
- 接收数据时,将首部以16位为单位相加,包括校验和,然后再取反,看结果是否为0,是0则保留,非0则丢弃
- 源地址和位目标地址:各占32位,表示发送端和接收端
- 选项:位数不定,最多40个字节,因为首部20个字节,一个IP数据报最大是60个字节
6. TCP与UDP
TCP
:Transmission Control Protocol 传输控制协议
UDP
:User Datagram Protocol 用户数据报协议
这两个协议均属于传输层协议
UDP
面向非连接的协议,传送数据不需要和服务器连接,只需要知道ip和监听端口,不需要链接没有目的的socket,只是将数据报投递出去,不管接收方是否成功接收到,是一种不可靠的传输。
UDP特点:
- UDP是无连接的,即通信时不需要创建连接(发送数据结束时也没有连接可以释放)所以减小了开销和发送数据前的时延;
- UDP采用最大努力交付,不保证可靠交付,因此主机不需要维护复杂的连接状态
- UDP是面向报文的,只在应用层交下来的报文前增加了首部后就向下交付IP层
- UDP是无阻塞控制的,即使网络中存在阻塞,也不会影响发送端的发送频率
- UDP的首部开销小,只有8个字节,它比TCP的20个字节的首部要短。
- 可以一对多,一对一,多对一
UDP的报文结构
应用层数据占用UDP报文段的数据字段。UDP首部只有4个字段,每个字段由2个字节组成,即UDP首部仅有8字节。
- 端口号:可以使目的主机将应用数据交给运行在目的端系统中端相应进程,执行分用功能
- 长度:该字段指示了在UDP报文段中的字节数(首部+数据)
- 检验和:接收方使用检验和来检查在该报文段中是否出现了差错,即差错检测。
UDP的校验和与IP校验和算法稍有不同:
- 没有将校验和位置0的过程,将3个字全部相加后按位取反码存入校验和中,相加的时候如果出现最高位有进位则回卷加到到最低位。
- 接收端将4个字全部相加,如果为11111111 11111111,如果这16位置有0出现,那么就出现了差错
举个例子:
0110011001100000
0101010101010101
1000111100001100
这是首部3个字 每个字16位,占2个字节,前两个字相加后得到
1011101110110101
然后与第三个字相加
10100101011000001
发现有溢出,那么将首位的1加到最后一位
0100101011000010
然后按位取反
1011010100111101
将该值存入到校验和
接收端能接收到后,将这4个字全部相加得出
1111111111111111
那么证明无差错
UDP在端到端基础上在运输层提供差错检测,在系统设计中被称为端到端原则
而UDP虽然提供差错检测,但它对差错恢复无能为力。这就需要用到可靠数据传输–TCP了
TCP
TCP特点:
- 面向连接
- 可靠传输
- 面向字节流
- 全双工服务
TCP的报文结构
如图,与UDP一样,首部包括源端口号和目的端口号,用于多路复用/分解来自上层或送到上层应用的数据。TCP首部也同样包括检验和字段
TCP首部还包含下列字段:
- 32比特的序号字段seq(sequence number field)和32比特的确认号字段ack(acknowledge number field)
- 4比特的首部长度字段(header length field),该字段指示了以32比特的字为单位的TCP首部长度。由于TCP选项字段的原因,TCP首部长度是可变的。(通常,选项字段为空,所以TCP首部的典型长度就是20字节)
- 16比特的接收窗口字段RW(receive window field),该字段用于流量控制,用于指示接收方愿意接收的字节数量。
- 可选和变长的选项字段(option field),该字段用于发送方和接收方协商最大报文段长度(MSS)时,或用作窗口调节因子时使用。
- 6比特的标志字段(flag field)。ACK比特用于指示确认字段中的值是有效的,即该报文段包括一个对已被接收报文段的确认。RST、SYN、FIN比特用于连接建立和拆除。PSH比特指示接收方应立即将数据交给上层。URG比特用于指示报文段里存在着被发送端的上层实体置为“紧急”的数据。紧急数据的最后一个字节由16比特的紧急数据指针字段指出。当紧急数据存在并给出指向紧急数据尾的指针的时候,TCP必须通知接收端的上层实体。在实践中,PSH、URG和紧急数据指针并没有使用。
在TCP通讯中,无论是建立连接,数据传输,友好断开,强制断开,都离不开Seq值和Ack值,它们是TCP传输的可靠保证。
序号字段seq和确认号字段ack:
- 序列号seq
TCP把数据看成一个无结构的、有序的字节流。一个报文段的序号因此是该报文段的首字节的字节流编号。
比如数据流由一个包含100000
字节的文件组成,其MSS是1000
字节,数据流的首字节编号是0
。该TCP将为该数据流构建100
个报文段。给第一个报文段分配序号0
,第二个则是1000
,第三个是2000
,以此类推。每一个序号被填入到相应TCP报文段首部的序号字段seq中。 - 确认号ack
TCP是全双工服务的,因此主机A在向主机B发送数据的同时,也许也在接收主机B的数据。
主机A填充进报文段的确认号是主机A期望从主机B收到的下一个字节的序号。
在上个例子中,假如服务端已经接收包含字节0-999
的报文段和包含字节2000-2999
的报文段,但由于某种原因,还未收到包含字节1000-1999
的报文段,那么将仍会等待字节1000
(及其后的字节)。因此服务端发给客户端的下一个报文段将在确认号ack字段中包含1000
。
因为TCP只确认该流中至第一个丢失字节为止的字节,所以TCP被称为累积确认。
总结:以上阐述了TCP和UDP的报文结构以及字段含义,TCP中的SEQ,seq,和ack,ACK将会在下文讲述的三次握手中用到,所以,先了解概念
7.DNS解析
首先来说一说域名解析的由来,我们为什么要进行域名解析?
我们要对一个服务器发送请求,那么我们就得知道对方的地址,比如说你要想拜访你的朋友,你先得知道他住在哪里。表示他住在哪里有两种方式
- 他直接告诉你他在哪里,比如说他住在朝阳区东四环朝阳公园桥外的东山墅,这是个地名,很好记,当你需要把这个位置告诉导航的时候,你只需要输入地名,可是导航地图不喜欢啊,它自己得解析这个地名得到经纬度,因为经纬度是它喜欢的表达方式
- 你的朋友脑子抽风,告诉你说,我的地址在经度:xxx, 纬度:xxx的地方,你瞬间就裂开了…这是人说的话吗?但是导航软件内部却更中意这样的表达方式
基于平衡这两种情况,我们就需要域名解析:
因特网上的主机,可以使用主机名或者IP地址标识他的位置
例如 www.baidu.com、www.google.com,这种属于主机名,很好记,但是长度不统一,没有规律,路由器处理起来不太方便,还有一种就是直接上ip,比如220.xxx.xxx.xxx,是一个定长的ip,这样路由器处理起来就比较方便了
那么给出DNS
概念:
- 一个由分层的DNS服务器实现的分布式数据库
- 一个使得主机能够查询分布式数据库的应用层协议
而DNS服务器通常是运行BIND软件的UNIX机器,DNS协议运行在UDP上,使用53
号端口
DNS通常是由其他应用层协议所使用的,包括HTTP、SMTP等。其作用则是:将用户提供的主机名解析为IP地址
目前的DNS服务器大致分为3种类型的DNS服务器:根DNS服务器
、顶级域DNS服务器
、权威DNS服务器
DNS解析过程
- 递归查询
- 迭代查询
这种利用了迭代查询和递归查询,从Client与本地DNS之间是递归查询,其余则是迭代查询。
所谓 递归查询过程 就是 “查询的递交者” 更替, 而 迭代查询过程 则是 “查询的递交者”不变。
从理论上讲,任何DNS查询既可以是迭代的也能是递归的。
在实际应用的过程中:
从请求主机到本地DNS服务器的查询是递归,其余查询是迭代的
DNS解析的过程:
- 发起基于域名的请求后,首先检查本地缓存(浏览器缓存–>操作系统的hosts文件)
- 如果本地缓存中有,直接返回目标IP地址,否则将域名解析请求发送给本地DNS服务器
- 如果本地DNS服务器中有,直接返回目标IP地址,到这一步基本能解析80%的域名。如果没有,本地DNS服务器将解析请求发送给根DNS服务器
- 根DNS服务器会返回给本地DNS服务器一个所查询的TLD服务器地址列表
- 本地DNS服务器再向上一步返回的TLD服务器发送请求,TLD服务器查询并返回域名对应的权威域名服务器的地址
- 本地DNS服务器再向上一步返回的权威域名服务器发送请求,权威域名服务器会查询存储的域名和IP的映射关系表,将IP连同一个TTL(过期时间)值返回给本地DNS服务器
- 本地DNS服务器会将IP和主机名的映射保存起来,保存时间由TTL来控制
- 本地DNS服务器把解析的结果返回给用户,用户根据TTL值缓存在本地系统缓存中,域名解析过程结束
DNS劫持问题
一种可能的域名劫持方式即黑客侵入了宽带路由器并对终端用户的本地DNS服务器进行篡改,指向黑客自己伪造的本地DNS服务器,进而通过控制本地DNS服务器的逻辑返回错误的IP信息进行域名劫持。
另一方面,由于DNS解析主要是基于UDP协议,除了上述攻击行为外,攻击者还可以监听终端用户的域名解析请求,并在本地DNS服务器返回正确结果之前将伪造的DNS解析响应传递给终端用户,进而控制终端用户的域名访问行为。
如何解决DNS劫持
DNS解析发生在HTTP协议之前,DNS解析和DNS劫持和HTTP没有关系,DNS协议使用的是UDP协议向服务器的53端口进行请求。
所以,可以使用HttpDNS的方案:使用 HTTP协议向DNS服务器的80端口进行请求,来规避DNS劫持
比如:http://119.29.29.29/d?dn=domain&ip=clientIp
8. TCP三次握手与四次挥手
在建立请求后,DNS解析完成后,就找到了服务器相应的地址,接下来要做的,就是要对服务器进行连接
在连接之前,首先要进行3次握手
三次握手
首先我不认为该图很准确,因为seq
与SEQ,ack
与ACK
不是同一个东西,大写的是个标志位,而小写的是存放信息的,看我下面的叙述
第一步
- 客户端的TCP首先向服务端的TCP发送一条特殊的TCP报文段。该报文段不包含应用层数据,该报文段首部中的一个
标志位(SYN比特)
被置为1,所以该报文段被称为SYN报文段
,另外,客户会随机选择一个初始序号client_isn
,并将该序号放置于该起始的TCPseq
报文段的序号字段中。 - 客户端和服务端最开始都处于
CLOSED
状态,发送过该SYN
报文段后,客户端TCP进入SYN_SENT
状态,等待服务端确认并将SYN
比特置为1的报文段。
第二步
- 收到
SYN
报文段后,服务端会为该TCP连接分配TCP缓存和变量,服务端TCP会进入SYN_RCVD
状态,等待客户端TCP发送确认报文段。 - 并向该客户端TCP发送允许连接的报文段,该报文段同样不包含应用层数据。该报文段首部的
SYN
比特被置为1,确认号字段被置为client_isn+1
。服务端还会选择自己的初始序号server_isn
,放到报文段首部的序号段中。该连接被称为SYNACK
报文段。
第三步
- 收到SYNACK报文段后,客户端也要为该TCP连接分配缓存和变量,客户端TCP进入
ESTABLISHED
状态,在此状态,客户端就能发送和接收包含有效载荷数据的报文段了。 - 并向服务端TCP发送一个报文段:这最后一个报文段对服务端的允许连接的报文表示了确认(将
server_isn + 1
放到报文段首部的确认字段中)。因为连接已经建立了,所以该SYN
比特被置为0。这个阶段,可以在报文段负载中携带应用层数据。 - 收到客户端该报文段后,服务端TCP也会进入
ESTABLISHED
状态,可以发送和接收包含有效载荷数据的报文段。
四次挥手
参与TCP连接的两个进程中的任何一个都能终止该连接,当连接结束后,主机中的资源(缓存和变量)会被释放。上边说到,SYN
和FIN
标志位分别对应着TCP连接的建立和拆除。
第一步
- 客户应用进程发出一个关闭连接的指令。会引起客户端TCP向服务端发送一个特殊的TCP报文段。该报文段即是将首部的一个标志位
FIN
比特置为1 - 同时,客户端进
入FIN_WAIT_1
状态,等待服务端的带有确认的TCP报文段。
第二步
- 收到该报文段后会向客户端发送一个确认报文段。
- 服务端TCP进入
CLOSE_WAIT
状态,对应客户端的TIME_WAIT
,表示被动关闭 - 客户端收到该报文段后,进入
FIN_WAIT_2
状态,等待服务端的FIN
比特置为1的报文段。
第三步
- 服务端发送自己的终止报文段,同样是把报文段首部的标志位
FIN
比特置为1。 - 服务端TCP进入
LAST_ACK
状态,等待服务端最后的确认报文段。
第四步
8. 客户端收到服务端的终止报文段后,向服务端发送一个确认报文段。同时,客户端进入TIME_WAIT
状态。
9. 假如ACK
丢失,TIME_WAIT
状态使TCP客户重传最后的确认报文,TIME_WAIT
通常会等待2MSL
(Maximum Segment Lifetime 最长报文段寿命)。经过等待后,连接就正式关闭,重新进入CLOSED
状态,客户端所有资源将被释放。
10. 服务端收到该报文段后,同样也会关闭,重新进入CLOSED
状态,释放所有服务端TCP资源。
在这里,或许有些读者会问了
为什么要经历3次握手与4次挥手呢?
2次握手
就好比如果是2次握手,比如你给要给小白兔发短信了你说,
大灰狼:“你是小白兔吗?收到请回复”
(由于信号不好,延迟了,让大灰狼重发)
大灰狼:“你是小白兔吗?收到请回复”
小白兔:“我是小白兔呀”
2次握手连接就已经建立了
大灰狼和小白兔畅聊到天亮
天快亮的时候,大灰狼那条延迟短信到达了小白兔手机上,小白兔误认为大灰狼还想找他,并给大灰狼发短信:
小白兔:我是小白兔啊,怎么了老铁
然而大灰狼并没有给小白兔发送什么信息,大灰狼早就洗洗睡了,小白兔等啊等,一直等到老死了都没等到渣狼,唉…这一辈子的等待,终究还是错付了。
放在这里呢:
客户端发出的第一个连接请求SYN
报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达服务端。本来这是一个早已失效的报文段。但服务端收到此失效的连接请求SYN
报文段后,就误认为是客户端再次发出的一个新的连接请求SYN
报文段。于是就向客户端发出ACK
确认报文段,同意建立连接。假设不采用三次握手,那么只要服务端发出确认,新的连接就建立了。
由于现在客户端并没有发出建立连接的SYN
请求,因此不会理睬服务端的确认,也不会向服务端发送数据。但服务端却以为新的运输连接已经建立,并一直等待客户端发来数据。这样,服务端的很多资源就白白浪费掉了。
事实上:TCP对有数据的TCP报文段必须确认的原则,所以,客户端对服务端的SYN
报文段必须回复一个ACK
报文段表示确认。并且,TCP不会为没有数据的ACK
超时重传,那么当服务端没收到客户端的ACK
确认报文段时,会超时重传自己的SYN
报文段,一直到收到客户端的ACK
为止。
4次握手
大灰狼:“你是小白兔吗?你今天拉屎了么?”
小白兔:“我是小白兔呀”
过了好长时间…
小白兔:“我今天拉屎了”
大灰狼:“这傻逼,不能一气儿说完吗”?
那么其实在实际过程中,本来服务端的确认ack 可以与syn一起发送的,没有必要单独分开发送,浪费资源
四次挥手
- 首先,当客户端数据已发送完毕,且知道服务端也全部接收到了时,就会去断开连接即向服务端发送
FIN
- 服务端接收到客户端的
FIN
,为了表示接收到了,就会向客户端发送ACK
- 但此时,服务端可能还在发送数据,并没有关闭TCP窗口的意思,所以服务端的
FIN
和ACK
并不是同步发的,只有当数据发送完了,才会发送FIN
所以要进行4次挥手
在四次挥手中,客户端为什么在TIME_WAIT后必须等待2MSL时间呢
最后服务器到客户端的ACK
报文段有可能丢失,因而使处在LAST_ACK
端的服务端收不到对已发送的FIN
报文段的ACK
报文段,从而服务端会去不断重传FIN
报文段。
而客户端就能在2MSL
时间内收到重传的FIN
报文段。接着客户端重传一次确认,重新启动2MSL
计时器。直至服务端收到后,客户端和服务端就都会进入CLOSED
状态,关闭TCP连接。
而如果客户端不等待2MSL
时间,而是在发送完ACK
确认后立即释放资源,关闭连接,那么就无法收到服务端重传的FIN
报文段,因而也不会再发送一次ACK
确认报文段,这样,服务端就无法正常进入CLOSED
状态,资源就一直无法释放了。
9.TCP流量控制,拥塞控制,可靠传输
其实传输层下的网络层IP协议,是个不靠谱的东西,不负责任,不能保证可靠传输,不能保证按序交付,也不能保证数据报的完整性
针对于这个不靠谱的东西:TCP只能自己弥补
超时重传
而发送端超时有两种情况:
- 发送数据超时
- 接收端发送
ACK
超时。
这两种情况都会导致发送端在TimeoutInterval内接收不到ACK
确认报文段。
解决方案:
1.如果发送端超时,那么直接重传
2.而如果是接收端发送ACK
超时,这种情况接收端实际上已经接收到发送端的数据了。那么当发送端超时重传时,接收端会丢弃重传的数据,同时再次发送ACK
。
流量控制
TCP连接的双方主机都会为该TCP连接分配缓存和变量。当该TCP连接收到正确、按序的字节后,就将数据放入接收缓存。上层的应用进程会从该缓存中读取数据,但不必是数据一到达就立即读取,因为此时应用程序可能在做其他事务。而如果应用层读取数据相对缓慢,而发送方发送得太多、太快,发送的数据就会很容易地使该连接的接收缓存溢出。
流量控制服务(flow-control service)
,是解决发送方发送数据太快而导致收方缓存溢出。
流量控制
是一个速度匹配服务,即发送方的发送速率与接收方应用程序的读取速率相匹配。
作为全双工协议,TCP会话的双方都各自维护一个发送窗口
和一个接收窗口(receive window)
的变量来提供流量控制。而发送窗口
的大小是由对方接收窗口
来决定的,接收窗口用于给发送方一个指示–该接收方还有多少可用的缓存空间。
1.发送窗口
发送方的发送缓存内的数据都可以被分为4类:
- 已发送,已收到ACK
- 已发送,未收到ACK
- 未发送,但允许发送
- 未发送,但不允许发送
发送窗口只有收到发送窗口内字节的ACK
确认,才会移动发送窗口的左边界
发送窗口里包含已发送,未收到ACK
与未发送,但允许发送
2.接收窗口
接收方的缓存数据分为3类:
- 已接收
- 未接收但准备接收
- 未接收而且不准备接收
接收窗口包含未接收但准备接收
接收窗口
只有在前面所有的报文段都确认的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,会先接收下来,接收窗口不会移动,并不对后续字节发送ACK
确认报文,以此确保发送端会对这些数据重传。
拥塞控制
我们这里简单的说一下拥塞控制,首先来一张很屌的图
- 慢开始:首先,在发送数据的时候,并不是一下子就到达了门限值,而是通过一些条件的限制,让发送的数据报呈现指数级的增长
- 一旦这个增长增加到了某一个
限制值
,那么就会进入拥塞避免
算法加法增大
,拥塞避免算法是线性增长的,当然,发送的数据报也会达到另外一个门限值,如果达到另外一个门限值的时候,就证明此时网络已经到达峰值,将进慢启动状态,同时,降低慢启动的门限值,同时新一轮的阈值变为原来的一半
这里推荐一篇写的很好的文章:
这个是关于TCP的拥塞控制
结束语
如果大家在阅读过程中发现有误的地方,还欢迎留言批评指正,同时也希望所有的猿猿们前程似锦
参考链接:
计算机网络中的七层模型
网络相关协议之HTTP
HTTP/HTTPS详解,对称加密已经非对称加密
网络相关之TCP
TCP如何保证可靠性
参考资料:
MJ底层原理逆向班:iOS签过程
《计算机网络》谢希任 第6版 电子工业出版社
《详解TCP/IP》电子工业出版社