[toc]
0. 概述与模型对比
- 参考地址1
- 参考地址2
- TCP 可靠性传输
-
模型对比图如下:
- OSI 参考模型分为 7 层:物理层、链路层、网路层、传输层、会话层、表示层、应用层
- TCP/IP 协议栈分为 4 层:网络接口层(物理层、链路层)、网际层(网络层IP)、传输层(UDP/TCP)、应用层(会话层、表示层、应用层)
- OSI 参考模型有点事概念清楚、理论完善,缺点是复杂而不实用
- TCP/IP 协议栈缺点为太简单,但被广泛使用
- 因此综合上述优缺点,我们讨论专门用于学习的 TCP/IP 5 层参考模型
- TCP/IP 5 层参考模型:物理层、数据链路层、网络层、传输层、应用层
1. 物理层(简单了解)
- 任务:透明地传输比特流。确定与传输媒体的接口的一些特性,即:机械特性(接口所用接线器的一些物理属性如形状尺寸),电气特性(接口电缆的各条线上出现的电压的范围),功能特性(某条线上出现的某一电平的电压的意义),过程特性(对于不同功能能的各种可能事件的出现顺序)
- 根据双方信息交互的方式,通信可划分为单向通信(或单工通信),双向交替通信(或半双工通信),双向同时通信(全双工通信)
- 传输媒体可分为两大类,即导引型传输媒体(双绞线,同轴电缆,光纤)和非导引型传输媒体(无线,红外,大气激光)
2. 数据链路层
- 数据链路层
- 帧:数据链路层的传输单元,由一个数据链路层首部和其携带的封包所组成协议数据单元,头部表名数据发送者、接受者、数据类型
- MAC 地址:每个设备具有的硬件地址。数据链路层负责 MAC 地址,在网卡的 ROM 中
- 链路:是从一个结点到相邻节点的一段物理链路,数据链路则在链路的基础上增加了一些必要的硬件(如网络适配器)和软件(如协议的实现)
- 无论在多么复杂的网络中,从逻辑意义上讲,真正的数据传输通道就是数据链路层中所定义的数据链路
- 数据链路层的三个基本问题是:封装成帧、透明传输和差错检测(可能还有物理地址寻址、流量控制、重发等)
- 循环冗余检验 CRC 是一种检错方法,而帧检验序列 FCS 是添加在数据后面的冗余码
- 数据链路层使用的信道主要有两种:点对点信道 和 广播信道,对应的两种的常见的协议为:点对点协议 PPP与以太网协议
- 以太网协议与点对点协议 PPP 均是数据链路层协议,区别在于以太网被设计用于广播网络,ppp 协议用于点对点网络,看帧格式就能明显看出区别来,以太网帧中有目标 Mac 地址,用于在多路信道确认目标端机器。而点对点协议中就没有目标 mac,点对点链路两端的主机事先就已经知道链路那头是哪个 ip 了
- 以太网采用的无连接、不可靠的工作方式,对发送的数据帧不进行编号,也不要求对方发回确认,目的站收到有差错帧就把它丢掉,其他什么也不做
2.1 封装成帧
- 其实就是在帧的数据部分添加帧首部和帧尾部,帧首尾用于帧定界,而数据部分才是传递给上层的数据(即 IP 数据报)
- MTU:Maximum Transfer Uint,帧的数据部分的最大长度,即 IP 数据报长度
- 我们将帧首部记作 SOH,帧尾部记作 EOT,用于帧定界
-
帧的逻辑结构如下图所示,SOH、EOT 的具体内容则和具体协议有关,例如 PPP 协议和以太网协议有不同的帧格式
2.2 透明传输
- 由于我们使用了帧定界符 SOH,EOT,但数据部分也有可能包含定界符,从而导致帧定界出错,因此需要实现透明传输
-
数据部分如果出现了 SOH,EOT,我们在其之前添加一个转义字符 ESC,这样就能将其识别为数据而不是帧定界符,如果数据部分也包含 ESC,则可以在 ESC 之前再添加一个 ESC
- 透明传输的方法主要有字节填充和零比特填充两种
2.3 差错处理
-
差错产生的原因:数据信号从发送端发送到物理线路时,由于物理线路存在噪声,因此数据信号经过物理线路的噪声,到达接收端时,已经是数据+噪声的叠加,因此差错无法避免
- 由于存在噪声,可能出现比特错误、帧丢失、帧重复和帧失序等错误
- 差错控制主要两种策略:检错和纠错
- 检测码:发送冗余信息让接收端用于检错
- 纠错码:发送足够的冗余信息让接收端能发现并自动纠错
- 由于纠错码实现比较复杂,检测码虽然不能纠错,但是足够简单,能够检测出差错,配合重传机制即可。所以广泛采用检测码
- 循环冗余检验(CRC)即为最常见的检错方式
2.4 循环冗余检验 CRC
- 为了保证数据传输的可靠性,CRC 是数据链路层广泛使用的一种检错技术
-
其概念性运算如图所示
-
CRC 校验举例如图所示
2.5 点对点协议 PPP
- 点对点协议 PPP 是数据链路层的一种协议,用于点对点信道,它的特点是:简单,只检测差错而不去纠正差错,不使用序号,也不进行流量控制,可同时支持多种网络层协议
- 简单:接收方每接收一个帧,就进行 CRC 检验,检验正确,就收下,否则就丢弃,它是不可靠传输,所以这就是简单的原因
- 用户计算机和 ISP 进行通信时使用 PPP 协议,例如 PPPoE 为宽带上网的主机使用的链路层协议(连着一条线,不用寻址)
-
PPP 协议帧格式如下
- F:即帧定界标志,规定为 0x7E,即 01111110
- A:下一个目的地的 MAC 地址,由于点对点无需 MAC 地址,因此固定位 FF,没什么用
- C:控制字段,固定位 03,没什么用
- 协议:2 字节,描述协议类型
- 0x0021:PPP 帧的信息字段就是 IP 数据报
- 0xC021:PPP 链路控制协议 LCP 的数据
- 0x8021:网络层的控制数据
- FCS:用于 CRC 校验
- 透明传输 采用字节填充或者零比特填充(SONET/SDH链路时),异步传输时使用字节填充,同步传输时使用零比特填充
2.6 广播信道、以太网与局域网
2.6.1 概述与关系
- 以太网:以太网是通信协议标准,该标准定义了在局域网(LAN)中采用的电缆类型和信号处理方法
- 局域网:在较小范围内组建的网络,通过交换器什么的连接各个PC机,比如一个实验室,一栋楼,一个校园内,这都市局域网,拿网线将两台计算机连在一起,这也能算是局域网
- 区别:以太网是一种局域网,而局域网却不一定是以太网,大多数局域网就是采用了以太网的这个标准
- 在局域网中,就采用的是广播信道:就是一台PC机发送数据给另一台PC机,在同一个局域网中的计算机都能接收到该数据,这就像广播一样,所以这种就叫做广播信道
2.6.2 CSMA/CD协议(半双工通信)
- 局域网是用广播信道的方式去传送数据,那么就会遇到问题,如果在局域网内有两个pc机同时在其中传播数据呢?就会发生碰撞,使两个数据都失效,那么如何解决这个问题呢,使用 CSMA/CD 协议来解决这类问题
- CSMA/CD 可简单描述为:多址接入、载波监听、碰撞检测
- 多址接入:该协议为多址接入协议,许多站点以多址接入的方式链接在一根总线上,其实就是局域网中总线网这种形式
- 载波监听:发送前监听,就是在发送数据前监听总线中是否有数据在传播,如果有就不发送。就是用电子技术检测总线上有没有其他计算机发送的数据信号
- 碰撞检测:
- 边发送边监听,在发送数据的中途也会监听总线中是否会有其它数据,当几个站同时在总线上发送数据时,总线上的信号电压摆动值将会增大(互相叠加)
- 当一个站检测到的信号电压摆动值超过一定的门限值时,就认为总线上至少有两个站同时在发送数据,表明产生了碰撞。 所谓“碰撞”就是发生了冲突。因此“碰撞检测”也称为“冲突检测”
- 检测到碰撞之后的处理 :
- 在发生碰撞时,总线上传输的信号产生了严重的失真,无法从中恢复出有用的信息来
- 每一个正在发送数据的站,一旦发现总线上出现了碰撞,就要立即停止发送,免得继续浪费网络资源,然后等待一段随机时间后再次发送
传播时延对载波监听的影响
- 争用期:发生碰撞所需要的最迟时间,即
- 10 Mbps 的以太网标准规定连接的最大长度为 2500 m,对应的争用期为 51.2μs,则在争用期内 10 Mbps 的以太网可发送 64 字节数据,因此我们发送帧至少要大于 64 字节,否则协议无法检测出是否发生碰撞
- 对于 100 Mbps 以太网,由于速度增大,如果要保证发送帧的最短有效帧仍然为 64 秒,则我们需要将争用期变为原来的十分之一 5.12μs,因此百兆以太网允许最大连接长度要为 250 m,其争用期为 5.12μs,在争用期内最多发送 64 字节数据,因此仍然符合最短有效帧的定义
- 由此可见,以太网的速率越快,以太网的有效距离就越短,对于 1000 Mbps 的以太网,要么放弃 CSMA/CD 协议改用其他协议,若仍要使用该协议,为了在争用期内检测出碰撞,就要再一次减小最大有效传输距离变为 25 m;若不想减小距离,则只能考虑将最短有效帧变为原来百兆以太网的 10 倍
- 最短有效帧:64 字节,就是上面这样算的,发送了 64 个字节之后,肯定就不会发生碰撞,以太网规定了最短有效帧长为 64 字节,凡长度小于 64 字节的帧都是由于冲突而异常中止的无效帧
- 根据 MAC 帧的格式,还有目的 MAC 地址 6 字节、源 MAC 地址 6 字节、类型 2 字节、FCS 4 字节,因此以太网数据部分最短 46 字节,最长即 MTU = 1500 字节
二进制指数类型退避算法
- 确定基本退避时间,一般就是争用期
- 确定参数
k = min(重传次数, 10)
- 从整数集合
[0, 1, ..., 2^k-1]
中随机选取一个数,记作 r,重传所需要等待的时延就是 r 倍的基本退避时间() - 当重传 16 次还不能成功则丢弃该帧,并向高层汇报
2.6.3 以太网
- 在局域网内部,以太网广播数据,并通过 MAC 地址确定目的方是否接受数据
- MAC 地址:48 bit,6 字节,前 3 个字节是由管理机构给各个厂家分配的,也就是说如果有厂家想生产网卡这类需要mac地址的东西,必须先像管理机构申请前三位字节; 所以网卡上的前三个字节就代表着某个厂家,后三个字节就是由厂家自己来设定的
- 每个网卡都拥有识别数据帧中 mac 地址的功能
-
以太网定义的数据帧格式如图所示
- 目的地址、源地址即 MAC 地址,类型为数据包的类型,数据部分即为 IP 数据包,FCS 用于 CRC 校验
- 开头的 8 个字节为前同步码(7 字节) + 帧定界(1 字节)
- 前同步码是为了让接收方有反应时间,在接受 MAC 帧后,并不能马上识别出帧开始定界符,没有那么快的反应分辨出来,所以需要在帧定界前面加同步码,使接收方有反应的时间
-
同步码都是 1010101010101 这样的 bit,前 7 个字节的同步码跟最后一个字节中的前 6 个bit位相同,只有最后两位不同,如图
3. 网络层
- 网际协议 IP 是 TCP/IP 体系中两个最主要的协议之一,是 TCP/IP 体系结构网际层的核心,配套 ARP、RARP、ICMP、IGMP 协议进行工作
- TCP/IP 协议中的网络层向上只提供简单灵活的,无连接的,尽最大努力交付的数据报服务;网络层不提供服务质量的承诺,不保证分组交付的时限所传送的分组可能出错,丢失,重复和失序;进程之间通信的可靠性由传输层负责
3.1 IP 地址
- ip 地址由 32 bit 的 0 或 1 组成,为了书写方便和易于理解,将 8 位划分为一组,每组书写对应的二进制数据,如 192.168.1.1
- 要上网就需要一个ip地址,这个ip地址不能和别人一样,独一无二,因为在网络上通信就是通过ip地址来找到你这台主机的,但是这个ip地址不是固定的(虽然 ISP 并不会分配一个真正的 IP 地址给你,其内部做了映射)
- 旧版的 IP 地址划分采用按类别划分,共分为 5 类,并通过子网号划分子网
划分子网 = <网络号>+<子网号>+<主机号>
- 我们现在采用的 ip 地址算法是:
无分类编址 = <网路前缀>+<主机号>
,利用子网掩码划分子网
3.2 ARP 协议
- ARP 协议虽然归为网络层协议,但其可以看做网络层和数据链路层的中间层,因为数据报在封装成帧时需要 MAC 地址,而 ARP 协议就是用于根据 IP 地址获取 MAC 地址
- 地址解析协议:通过 ip 地址来解析主机的 mac 地址
- 若在一个局域网中,A 知道 B 的 ip 地址,想获取 B 的 mac 地址,则发送广播(若有缓存则不广播,直接拿到),B 收到后发现自己就是这个 ip 地址,因此将 mac 地址返回给源主机,这样就能拿到 mac 地址,封装成帧进行通信了
- 若不在一个局域网中而是跨网络通信,A 通过 ARP 获取到的是局域网中的路由器的 MAC 地址,封装成帧交给路由器,路由器接收到后,解帧,后续操作则交由该路由器
- 注意:路由器工作在网络层,其具有 ARP 协议,每个路由器都能识别出目标 ip 地址在哪个路由器上,这其中涉及到了很多算法,路由器能根据目标 ip 地址找到下一跳路由器的 mac 地址,然后一步一步跳下去,直至路由器发现目标 ip 地址在当前子网中,则用 ARP 广播得到 MAC 地址(有缓存则不广播)
ARP 详解
- 注意路由器路由器间一般是直连的,大多采用 PPP 协议
- 发送方是主机,要把 IP 数据报发送到本网络上的另一个主机,这时用 ARP 广播找到目的主机的硬件地址
- 发送方是主机,要把 IP 数据报发送到另一个网络上的一个主机,这时用 ARP 找到本网络上的一个路由器的 MAC 地址,用该 MAC 地址和最终 IP 地址封装成帧发给路由器;路由器在接收到帧后,解帧,然后根据最终 IP 地址转发该数据报(根据缓存或者根据路由选择算法确定),这一步封装成帧的 MAC 地址为下一个路由器的 MAC 地址,知道转发至最终路由器确定 IP 在本子网上
- 发送方是路由器,要把 IP 数据报转发到本网络上的一个主机,这时用 ARP 广播找到目的主机的硬件地址(最终的路由器找到最终的主机的 MAC 使用该步)
- 发送方是路由器,要把 IP 数据报转发到另一个网络上的一个主机。这时用 ARP 找到本网络上的一个路由器的硬件地址。剩下的工作由这个路由器来完成
3.3 IP 协议
- IP 协议的责任就是把数据从源地址传送到目的地,它不负责保证传送可靠性,流控制,包顺序和其它对于主机到主机协议来说很普通的服务
IP 数据包
-
IP 数据包的格式如图所示
- IP 数据包头部的固定部分共 20 字节,每行 32 bit,4 字节,共 5 行
- 第一行:基本信息
- 版本:4 bit,IP 协议版本,普遍为 IPv4,以后可能 IPv6
- 首部长度:4 bit,最大值为 15,单位为 4 字节,因此首部最大长度为 60 字节,除去固定的 20 字节,可选字段和填充合起来不得超过 40 字节
- 服务类型:8 bit,有些要传输的数据要立马传达到对面,比如视频,语音这样的,不能跟邮件慢慢吞吞的达到对方一样,需要立马送达,这就是为什么需要这个区分服务了
- 总长度:16 bit,描述整个数据包的总长度(头部+数据),但数据链路层中,帧的数据部分最长不能超过 1500 个字节(MTU),因此数据包不能太大,如果太大就需要分片
- 第二行:分片信息
- 标识:16 bit,一个计数器,每产生一个数据包,计数器就加 1,当数据包被分片时,他们的标识是一样的,这样接收方能识别出各个数据包片是同一个数据包,以重新组合在一起
- 标志:3 bit,占3位,第一位暂时没意义,第二位 DF:不能分片的意思,为1时,不能分片,为 0 就可以分片 第三位 MF 后续还有分片的意思,为 0 代表这是若干数据包中的最后一片
- 片偏移:13 bit,在较长的分组在分片后,某片在原分组中的相对位置,几个例子,1111,1111,1111,1111 这16位,分成4个数据包分片来发,第一个数据包分片的片偏移为 1,第二个为 5,第三个为 9,第四个为 13,就是这个意思,但实际上片偏移以 8 个字节为偏移单位,也就是说,每个分片的长度一定是 8 字节的整数倍,上面是以 4 bit 来举例说明问题,实际上单位是 8 个字节(64 bit)为单位
- 第三行:附加信息
- 生存时间:8 bit,也就是 ping 命令中显示的 TTL 字段,跳数限制,每经过一个路由器,就减 1,当跳到 0 后,就丢弃该数据包。window 系统的起始 TTL 为32、Linux 64、xp:128
- 上层协议标识:8 bit,数据包中数据部分使用的是什么协议,方便目的主机的 IP 层知道讲数据部分上交给哪个处理。(也就是下一章要将的 TCP 还是 UDP 协议)
- 头部检验和:16 bit,这个字段只检验数据报的首部,但不包括数据部分。这是因为数据报每经过一个路由器,路由器都要重新计算一下首部检验和(一些字段,如生存时间、标志、片偏移等都可能发生变化)不检验数据部分可减少计算的工作量
- 第四行:源 IP 地址,32 bit
- 第五行:目标 IP 地址,32 bit
- 可选部分:为了使整个数据包为整数个字节而设置的
3.4 ICMP 协议
- ICMP 协议是一种面向无连接的协议,用于传输出错报告控制信息,它是一个非常重要的协议,它对于网络安全具有极其重要的意义
- 它是 TCP/IP 协议族的一个子协议,属于网络层协议,主要用于在主机与路由器之间传递控制信息,包括报告错误、交换受限控制和状态信息等
- 当遇到 IP 数据无法访问目标、IP 路由器无法按当前的传输速率转发数据包等情况时,会自动发送 ICMP 消息
- 在 IP 首部中,其上层协议类型值为 1
- 主要包括:ICMP 差错报告报文、ICMP 询问报文
3.4.1 ICMP 差错报告报文
- 检测在传送数据的过程中,发生的错误,如果发生了错误,会通过该协议返回给源主机一个带有错误原因的数据包,大致有如下可能原因
- 终点不可达:发送数据后,路由器或主机不能完成交付数据报时,就会往源主机发送终点不可达报文
- 源点抑制:当路由器或主机由于网络拥塞而丢弃数据报时,返回一个源点抑制报文
- 超时:
- 参数问题,在 ip 数据包中的首部有的字段不正确时,丢弃该报,返回参数问题报文
- 改变路由(重定向):路由器把改变路由报文发送给主机,让主机下次直接经过改变后的路由器
3.4.2 ICMP 询问报文
- 回送请求和回答:主机向特定目标发出询问,收到此报文必须返回一个 ICMP 回送回答报文,用于测试目的站是否可达(ping 命令)
- 时间戳请求和回答:请某个路由器或主机回答当前的日期和时间,用于进行时钟的同步和测量时间
3.5 IGMP 协议
- IGMP 是 TCP/IP 协议族中负责 IP 组播成员管理的协议,用来在 IP 主机和与其直接相邻的组播路由器之间建立、维护组播组成员关系
- IGMP 提供多点传送功能,将一个 ip 包拷贝给多个 host 采用该协议
-
IGMP 协议用于多播,即接收到一个 ip 包后,拷贝多份并并转发给相连的路由器或主机
-
其工作流程大致如图
3.6 路由
3.6.1 路由的原理
- 当给同一个子网中的主机发送数据包时,直接将 IP 分组组帧广播即可(APR 能直接获取到 MAC 然后组帧)
- 若要给不同子网的主机发送数据包,则要选择一个当前子网中的可达路由器,将 IP 分组转发给该路由器,让路由器将 IP 分组转发到目的地
- 如果没有找到这样的路由器,主机就把 IP 分组转发给默认网关;默认网关是每台主机上的一个配置参数,它是当前子网的某个路由器端口的 IP 地址
- 路由器转发 IP 分组时,只根据 IP 分组中的目的 IP 地址,查表或做路由选择把 IP 分组送出去
- 同主机一样,路由器也要判定所处子网是否目的子网,如果是,就直接把分组发给对应主机(APR 获取 MAC,然后组帧),否则,继续选择下一个路由转发
- 路由器也有它的默认网关,用来传送不知道往哪儿送的 IP 分组,这样,通过路由器把知道如何传送的IP分组正确转发出去,不知道的 IP 分组送给“默认网关”路由器,这样一级级地传送,IP 分组最终将送到目的地,送不到目的地的 IP 分组则被网络丢弃了
3.6.2 其他补充
- 路由选择算法(了解):将收集到的不同信息填入路由表中,根据路由表可将目的网络与下一站(nexthop)的关系告诉路由器。路由器间互通信息进行路由更新,更新维护路由表使之正确反映网络的拓扑变化,并由路由器根据量度来决定最佳路径。这就是路由选择协议(routing protocol),例如路由信息协议(RIP)、开放式最短路径优先协议(OSPF)和边界网关协议(BGP)等
- 路由转发协议(了解):转发即沿寻径好的最佳路径传送信息分组。路由器首先在路由表中查找,判明是否知道如何将分组发送到下一个站点(路由器或主机),如果路由器不知道如何发送分组,通常将该分组丢弃;否则就根据路由表的相应表项将分组发送到下一个站点,如果目的网络直接与路由器相连,路由器就把分组直接送到相应的端口上。这就是路由转发协议(routed protocol)。
4. 传输层
4.1 概述
- 传输层提供端到端通信服务,即进程和进程之间的通信
- 通过 ip 仅能识别到主机,要识别到具体的进程,则需要利用端口
- 端口:16 bit 描述,故端口范围为 0 - 65535,进程之间的通讯,都要依靠端口,一个进程对应一个端口
- 熟知端口:0 - 1023,描述一些固定的端口号,如 http 的 80
- 登记端口:1024 - 49151,比如 3306,8080 等
- 客户端端口:49152-65535,一般我们使用某个软件,比如 QQ,其会随机拿该范围的端口,而不是去那前面固定的,以避免冲突,等通讯结束时,会释放该端口
- 传输层就是将两个端口连起来通信的介质,其中重要的就是靠两个协议,UDP 和 TCP 协议
4.2 UDP 协议
4.2.1 UDP 概述与特点
- UDP 即用户数据报协议,其特点为无连接、不可靠
- 无连接:通讯之前不需要建立连接,直接传输数据
- 不可靠:将数据报的分组从一台主机发送到另一台主机,但并不保证数据报能够到达另一端
- 在 UDP 情况下,虽然可以确保发送消息的大小,却不能保证消息一定会达到目的端
- 没有超时和重传功能,当 UDP 数据封装到 IP 数据报传输时,如果丢失,会发送一个 ICMP 差错报文给源主机,即使出现网络阻塞情况
- UDP 也无法进行流量控制,传输途中即使出现丢包,UDP 也不负责重发,甚至当出现包的到达顺序杂乱也没有纠正的功能
4.2.2 UDP 报文结构
-
UDP 报文作为 IP 包的数据部分进行封装
-
UDP 报文的格式如图
- UDP 首部共 64 bit,8 字节
- 源端口号:16 bit,源主机进程端口
- 目标端口号:16 bit,目标主机进程端口
- UDP 报文长度:16 bit,即 UDP 首部 + 数据 的总长度
- 检验和:校验首部和伪首部
- UDP 伪首部:概念上的东西,其实就是 IP 层的一些数据,主要用于检验和
- 注意,这里的检验和是为了 UDP 首部的可靠性而设计的,并不是为了 UDP 传输的可靠性,通过检验和,提供可靠的 UDP首部,
- 由于一个进程可能接受多个进程过来的报文,要通过 “源 IP 地址”、“目的 IP 地址”、“协议号”、“源端口号”、“目标端口号” 进行区分,因此检验和需要检验伪首部+首部,不正确的 UDP 报文直接丢弃
4.2.3 UDP 应用举例
- 选择 UDP 必须要谨慎,在网络质量令人十分不满意的环境下,UDP 协议数据包丢失会比较严重
- 由于 UDP 的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用 UDP 较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响
- 应用层协议中 DNS,也就是根据域名解析 ip 地址的一个协议,他使用的就是 UDP
- DHCP 这个是给各电脑分配 ip 地址的协议,其中用的也是 UDP 协议
- IGMP,我们说的多播,也就是使用的 UDP
4.3 TCP 协议
4.3.1 TCP 概述
- TCP 协议是面向连接的、可靠传输、有流量控制、拥塞控制、面向字节流传输等很多优点的协议
- 当应用层向 TCP 层发送用于网间传输的、用 8 位字节表示的数据流,TCP 则把数据流分割成适当长度的报文段,最大传输段大小(MSS)通常受该计算机连接的网络的数据链路层的最大传送单元(MTU)限制
- 之后 TCP 把数据包传给 IP 层,由它来通过网络将包传送给接收端实体的 TCP 层
TCP 提供可靠性传输
- 在发送数据前先使用三次握手建立连接,数据发送完毕后使用四次挥手释放连接
- TCP 校验和会校验数据部分,同时采用连续 ARQ 协议(回退N,Go-back-N;超时自动重传)配合滑动窗口协议来传输数据以确保传输数据的可靠性
- 采用滑动窗口协议,通过动态调整窗口大小来进行流量控制
- TCP 使用慢启动、拥塞避免、快重传和快恢复来进行拥塞控制
4.3.2 TCP 报文结构
-
TCP 报文结构如图所示,相比 UDP 报文结构,其多了很多的控制字段
- 源端口号:16 bit
- 目标端口号:16 bit
- 序列号:32 bit,因为 TCP 是面向字节流的,他会将报文都分成一个个字节,给每个字节进行序号编写,比如一个报文有 900 个字节组成,那么就会编成 1-900 个序号,然后分几部分来进行传输,比如第一次传,序列号就是 1,传了 50 个字节, 那么第二次传,序列号就为51,所以序列号就是传输的数据的第一个字节相对所有的字节的位置
- 确认应答:如刚说的例子,第一次传了 50 个字节给对方,对方也会回应你,其中带有确认应答,就是告诉你下一次要传第 51 个字节来了,所以这个确认应答就是告诉对方要传第多少个字节了(传的的以确认 + 1)
- 首部长度:4 bit,单位是 32 bit,4 字节,因此报文头部最长 60 字节
- 保留控制位:6 bit,给以后有需要在用
- 控制位:6 bit
- URG:紧急,当 URG 为 1 时,表名紧急指针字段有效,标识该报文是一个紧急报文,传送到目标主机后,不用排队,应该让该报文尽量往下排,让其早点让应用程序给接受
- ACK:确认,当 ACK 为1时,确认序号才有效。当 ACK 为0时,确认序号没用
- PSH:推送,当为 1 时,当遇到此报文时,会减少数据向上交付,本来想应用进程交付数据是要等到一定的缓存大小才发送的,但是遇到它,就不用在等足够多的数据才向上交付,而是让应用进程早点拿到此报文,这个要和紧急分清楚,紧急是插队,但是提交缓存大小的数据不变,这个推送就要排队,但是遇到他的时候,会减少交付的缓存数据,提前交付
- RST:复位,报文遇到很严重的差错时,比如 TCP 连接出错等,会将 RST 置为 1,然后释放连接,全部重新来过
- SYN:同步,在进行连接的时候,也就是三次握手时用得到,下面会具体讲到,配合 ACK 一起使用
- FIN:终止,在释放连接时,也就是四次挥手时用的
- 窗口:指发送报文段一方的接受窗口大小,用来控制对方发送的数据量(从确认号开始,允许对方发送的数据量),也就是后面需要讲的滑动窗口的窗口大小,用于流量控制
- 检验和:检验首部和数据这两部分,和 UDP 一样,需要拿到伪首部中的数据来帮助检测(可靠性的基础,此外还有重传)
- 选项:长度可变,介绍一种选项,最大报文段长度,MSS;能够告诉对方 TCP,我的缓存能接受报文段的数据字段的最大长度是 MSS 个字节;如果没有使用选项,那么首部固定是 20 个字节
- 填充:配合选项,就是为了让其成为整数个字节
4.3.3 面向连接:三次握手
- TCP 是面向连接的,在通信之前,会先通过三次握手的机制来确认两端口之间的连接是否可用;而 UDP 不需要确认是否可用,直接传
-
三次握手的步骤如图所示:
- 说明:ACK 为确定标志,SYN 为同步标志,seq 为序号,ack 为确认序号(值为成功接收的序号+1);只有 ACK=1 时,ack 才有用,此时表示该报文为确认报文
- 一开始客户端和服务端都是关闭状态,但是在某个时刻,客户端需要和服务端进行通信,此时双方都会各自准备好端口,服务器段的端口会处于监听状态,等待客户端的连接
- 首先,客户端要知道自身的端口号,和目的进程的端口号,这样才能发起请求,且服务端要处于监听状态(LISTEN),才能握手
- 第一次握手:客户端想与服务器进行连接了,所以状态变为主动打开,同时发送一个连接请求报文给服务器段 SYN=1,并且会携带 x 个字节过去;发送完请求连接报文后,客户端的状态就变为了 SYN_SENT,可以说这个状态是等待发送确认(为了发送第三次握手时的确认包)
- 第二次握手:服务端接收到连接请求报文后,从 LSTTEN 状态变为被动打开状态,然后给客户端返回一个报文;这个报文有两层意思,一是确认报文,而可以达到告诉客户端,我也打开连接了;发完后,变为SYN_RCVD 状态(也可以说是等待接受确认状态,接受客户端发过来的确认包)
- 第三次握手:客户端得到服务器端的确认和知道服务器端也已经准备好了连接后,还会发一个确认报文到服务器端,告诉服务器端,我接到了你发送的报文,接下来就让我们两个进行连接了。客户端发送完确认报文后,进入 ESTABLISHED,而服务器接到了,也变为 ESTABLISHED
为什么是三次握手
4.3.4 同时打开连接请求
- 正常情况下,通信一方请求建立连接,另一方响应该请求,但是如果出现,通信双方同时请求建立连接时,则连接建立过程并不是三次握手过程,而且这种情况的连接也只有一条,并不会建立两条连接
- 同时打开连接时,两边几乎同时发送 SYN,并进入 SYN_SENT 状态,当每一端收到 SYN 时,状态变为 SYN_RCVD,同时双方都再发 SYN 和 ACK 作为对收到的 SYN 进行确认应答
-
当双方都收到 SYN 及相应的 ACK 时,状态变为 ESTABLISHED
4.3.5 可靠传输:连续 ARQ 协议、滑动窗口协议
- 主要通过数据编号、积累确认、以字节为单位的滑动窗口、超时重传时间、快速重传这四个方面来达到可靠传输的目的
- 快速重传:在滑动窗口中的应用,比如传了1234 6到服务器端,老办法是在 4 之后的所有数据度要重新传,而引入拥塞控制的快速重传就只需要等待传了 5 这个序号,就可以继续往下接收数据了(连发三个 5 的确认包)
停止等待 ARQ 协议
- ARQ 协议,即自动重传请求协议,是 OSI 模型中用于数据链路层和传输层的纠错协议之一,通过确认和超时两个机制来在不可靠的信道上实现可靠性传输
- ARQ 包括停止等待 ARQ 协议和连续 ARQ 协议,其中后者需要配合滑动窗口协议使用
- TCP 会划分报文,对数据进行按序分组并按序发送,停止等待 ARQ 协议在发送完一个分组后,就会暂停下来等待收到确认,若收到了确认就继续发送下一个分组
- 若超过一定的时间没有收到确认,则认为刚才的分组丢失,所以会自动重新发送刚才发送过的分组,然后再次停下来等待确认,即所谓的超时重传
- 超时重传的原理即通过一个超时定时器实现,每发送完一个分组,则设置一个超时定时器,若计时器到期之前未收到确认则触发超时重传,若收到确认信息则撤销该定时器,继续发送下一分组数据
- 通过上述确认和超时重传机制,就可以在不可靠的网络上实现可靠性传输
- 停止等待 ARQ 协议的优点是简答,但也有很严重的缺点,就是信道利用率太低
连续 ARQ 协议
- 由于停止等待 ARQ 协议信道利用率太低,所以需要使用连续 ARQ 协议来进行改善,这个协议会连续发送一组数据包,然后再等待这些数据包的 ACK
- 连续 ARQ 协议以字节为单位进行传输,即会对数据以字节为大小按序编号,但我们在描述时使用术语
分组
(停止等待 ARQ 协议可能是多个字节的分组为单位) - 发送方采用流水线传输,即发送方可以连续发送多个分组,不必每发完一个分组就停下来等待对方确认
- 连续 ARQ 协议通常是结合滑动窗口协议来使用的,发送方需要维持一个发送窗口
- 位于发送窗口内的分组都可以连续发送出去,而不需要等待对方的确认,这样就提高了信道利用率
- 而接收方采用累积确认的方式,也就是说接收方不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认,发送方如果收到了这个分组确认信息,则表示到这个分组为止的所有分组都已经正确接收到了
- 发送方收到确认后,根据确认序号往后滑动窗口,若一定时间后未收到确认,则触发超时重传机制,重发窗口内的数据
- 累积确认的优点是容易实现,即使窗口中间数据的确认丢失也不必重传;但缺点是,不能正确的向发送方反映出接收方已经正确收到的所以分组的信息;比如发送方发送了前 5 个分组,而中间的第 3 个分组丢失了,这时候接收方只能对前 2 个发出确认,而不知道后面 3 个分组的下落,因此只能把后面的 3 个分组都重传一次,这种机制叫 Go-back-N(回退N),表示需要再退回来重传已发送过的 N 个分组
滑动窗口协议
- 滑动窗口协议在在发送方和接收方之间各自维持一个滑动窗口,发送发是发送窗口,接收方是接收窗口,而且这个窗口是随着时间变化可以向前滑动的
- 它允许发送方发送多个分组而不需等待确认,TCP 的滑动窗口是以字节为单位的
-
如下图所示,发送窗口中有四个概念:
- 已发送并收到确认的数据(不在发送窗口和发送缓冲区之内)
- 已发送但未收到确认的数据(位于发送窗口之内,会触发超时重传)
- 允许发送但尚未发送的数据(位于发送窗口之内,且在下次窗口滑动后发送)
- 发送窗口之外的缓冲区内暂时不允许发送的数据
- 对于已发送但未收到确认的数据,都暂时保留在缓冲区,以便在超时重传时使用
-
只有当发送方接收到接收方的确认报文时,发送方才会使用滑动窗口协议向前滑动窗口
- 若发送方经过一段时间后没有收到已发送的数据的确认(由超时控制器控制),则触发超时重传,在滑动窗口中即 Go-back-N 回退机制
- 此外,通过设置发送方的窗口大小进行流量控制和拥塞控制
4.3.6 流量控制:动态调整窗口大小
- 所谓的流量控制就是让发送方的发送速率不要太快,让接收方来得及接受,利用滑动窗口机制可以很方便的在 TCP 连接上实现对发送方的流量控制
- 我们已经知道,基于连续 ARQ 的可靠性传输中,接收方会给出确认报文,而流量控制就是通过在确认报文中告诉接口方可用窗口大小来进行的
- 接收方在发送确认报文时,会同时给出接收方的可用窗口大小,
- 发送方在接收到确认报文时,通过报文中的可用窗口大小动态调整发送窗口大小,其不能超过接收方给出的接收窗口的数值,从而达到流量控制的目的
死锁的产生和避免
- 当发送方收到了一个窗口为 0 的确认报文后,发送者便停止发送,等待接收者的后续确认报文以整窗口大小
- 但是如果这个窗口不为 0 的后续确认报文在传输过程丢失,会导致发送方一直等待下去,而接收方以为发送方已经收到该应答,等待接收新数据,这样双方就相互等待,从而产生死锁
- 为了避免流量控制引发的死锁,TCP 引入持续计时器
- 若发送方收到对方的零窗口通知,就启动持续计时器,若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带1字节的数据)- 若接收方仍然返回零窗口,则重置该计时器继续等待
- 若窗口不为0,则表示应答报文丢失了,此时重置发送窗口后开始发送,这样就避免了死锁的产生
4.3.7 拥塞控制
- 其实跟流量控制差不多,但是站的角度更大,此时既考虑了对方接收不过来,缓存太多溢出导致,又考虑在线路中,线路上的传输速率就那么大,但是有很多人同时用,发送的数据太多,就会使线路发现拥塞,也就是路由器可能转发不过来,导致大量数据丢失这两个问题
- 所以拥塞控制这个解决方案,大概意思就是当检测到有网络拥塞时,就会让自己的滑动窗口变小,但具体是怎么变化的,就是根据算法来算了
- 发送窗口的上限值 = Min[rwnd,cwnd]
- rwnd:接收端窗口(Reciver Window),即确认报文中给出的窗口大小
- cwnd:拥塞窗口(Congestion Window),发送端根据自己估计的网络拥塞程度而设置的窗口值,是来自发送端的拥塞控制
- 发送窗口是取两个中较小值,通过设置发送窗口的大小进行流量控制和拥塞控制
- 拥塞控制主要涉及 4 个算法:慢启动(Slow-start),拥塞避免(Congestion Avoidance),快重传(Fast Restrangsmit)和快恢复(Fast Recovery)
慢启动原理
- 当主机开始发送数据时,如果立即将较大的发送窗口的全部数据字节都注入到网络中,那么由于不清楚网络的情况,有可能引其网络拥塞
- 因此比较好的方法是试探一下,即从小到达逐渐增大发送端的拥塞控制窗口数值
- 通常在刚刚开始发送报文段时可先将拥塞窗口 cwnd 设置为一个最大报文段的 MSS 的数值
- 在每收到一个对新报文段确认后,将拥塞窗口增加至多一个 MSS 的数值,当 rwind 足够大的时候,为了防止 cwind 的过快增长引起网络拥塞,还需要引入另外一个变量:慢开始门限 ssthresh 来进行拥塞避免
- 当 cwind 到达 ssthresh 值后则过了慢启动阶段,不再指数增长,而是改为线性增长
拥塞控制:慢启动 + 拥塞避免
- TCP 初始化连接,将 cwind 设置为 1,并设置 ssthresh 初始值
- 执行慢开始算法:cwind 以指数规律增长,直到 cwind == ssthresh 后,开始执行拥塞避免,即让 cwind 线性增长
- 当网络发生拥塞时,把 ssthresh 更新为原值的一半, cwind 设置为 1,重新开始慢启动
快重传和快恢复
- 一条 TCP 连接有时会因等待重传计时器的超时而空闲较长的时间,慢启动和拥塞避免无法很好的解决这类问题,因此提出了快重传和快恢复的拥塞控制方法
- 快重传算法并非取消了重传机制,只是在某些情况下更早的重传丢失的报文段 :
- 如果当发送端接收到三个重复的确认 ACK 时,则断定分组丢失,立即重传丢失的报文段,而不必等待重传计时器超时
- 相当于利用接收方报告拥塞丢失,由于重传计时器可能要等比较长,因此让接收方重复报告三次确认,让发送方明白丢失了对应的内容
- 例如:M1,M2,M3 -----> M1,M3,缺失 M2,则接收方向发送方持续发送 M2 重复确认,当发送方收到 M2 的三次重复确认,则认为 M2 报文丢失,启动快重传机制,重传数据,其他数据发送数据放入队列,待快重传结束后再正常传输
- 快恢复算法则用于让 cwind 跳过慢启动阶段 :
- 当发送方连续收到接收方发来的三个重复确认时,就执行“乘法减小”算法,把 ssthresh 减半,这是为了预防网络发生拥塞
- 由于发送方现在认为网络很可能没有发生拥塞,因此现在不执行慢开始算法,而是直接把 cwnd 设置为 ssthresh 减半后的值,然后开始执行拥塞避免算法,使拥塞窗口的线性增大,这样就跳过了慢启动阶段
4.3.8 释放连接:四次挥手
-
通信完成后,需要释放连接,TCP 通过四次挥手释放连接,其步骤大致如图所示
第一次挥手:从 ESTABLISHED 变为主动关闭状态,客户端主动发送释放连接请求给服务器端,FIN=1;发送完之后就变为 FIN_WAIT_1 状态,这个状态可以说是等待确认状态
-
第二次挥手:
- 服务器接收到客户端发来的释放连接请求后,状态变为CLOSE_WAIT,然后发送确认报文给客户端,告诉他我接收到了你的请求
- 为什么变为 CLOSE_WAIT,原因是是客户端发送的释放连接请求,可能自己这端还有数据没有发送完呢,所以这个时候整个 TCP 连接的状态就变为了半关闭状态,服务器端还能发送数据,并且客户端也能接收数据,但是客户端不能在发送数据了,只能够发送确认报文
- 客户端接到服务器的确认报文后,就进入了FIN_WAIT_2状态。也可以说这是等待服务器释放连接状态
第三次挥手:服务器端所有的数据度发送完了,认为可以关闭连接了,状态变为被动关闭,所以向客户端发送释放连接报文,发完之后自己变为 LAST_WAIT 状态,也就是等待客户端确认状态
-
第四次挥手:
- 客户端接到释放连接报文后,发送一个确认报文,然后自己变为 TIME_WAIT,而不是立马关闭,因为客户端发送的确认报文可能会丢失,丢失的话服务器就会重传一个FIN,也就是释放连接报文,这个时候客户端必须还没关闭
- 当服务器接受到确认报文后,服务器就进入 CLOSE 状态,也就是关闭了
- 但是由于上面说的这个原因,客户端必须等待一定的时间才能够进入 CLOSE 状态
4.3.9 同时释放连接
- 正常情况下,通信一方请求连接关闭,另一方响应连接关闭请求,并且被动关闭连接
- 但是若出现同时关闭连接请求时,通信双方均从 ESTABLISHED 状态转换为 FIN_WAIT_1 状态。
- 任意一方收到对方发来的 FIN 报文段后,其状态均由 FIN_WAIT_1 转变到 CLOSING 状态,并发送最后的 ACK 数据段。当收到最后的 ACK 数据段后,状态转变化 TIME_WAIT,
- 在等待 2MSL 时间后进入到 CLOSED 状态,最终释放整个 TCP 传输连接
-
上述过程大致如图所示
4.3.10 补充
关闭连接时等待 2 MSL 的原因
- TIME_WAIT 状态就是用来重发可能丢失的刚发出去的 ACK 报文:在 Client 发送出最后的 ACK ,但该 ACK 可能丢失,Server 如果没有收到 ACK,将不断重复发送 FIN 片段以再次关闭
- 2MSL 是两倍的 MSL(Maximum Segment Lifetime),MSL 指一个片段在网络中最大的存活时间,2MSL 就是一个发送和一个回复所需的最大时间,如果直到 2MSL,Client都没有再次收到 FIN,推断服务端收到信息,结束 TCP
为什么连接的时候是三次握手,关闭的时候却是四次挥手
- 因为当 Server 端收到 Client 端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的
- 但是关闭连接时,当 Server 端收到 FIN 报文时,很可能并不会立即关闭 SOCKET,所以只能先回复一个 ACK 报文,告诉 Client 端,"你发的 FIN 报文我收到了";只有等到我 Server 端所有的报文都发送完了,我才能发送 FIN 报文,因此不能一起发送,故需要四步握手
TCP 的 4 个定时器
- 超时重传定时器:对报文段的等待确认时间(连续 ARQ 协议)
- 持续定时器:用于解决流量控制时的死锁问题
- Time_Wait 计时器:关闭连接时的计时器,值一般为 2 MSL
- keep alive 计时器:连接后很久没发送信息,确认是否还活着
5. 应用层
5.1 概述
- 位于计算机网络体系结构的最上层,前面四层做的所有事情就是为了他服务,也是设计和建立计算机网络的最终目的
- 通俗的讲,就是我们开发的应用软件,就处于这一层,比如,QQ、浏览器访问网页等
- 应用层的通信模式大致有两种:C/S 模式和 P2P 模式
- C/S 模式:经典的客户端/服务端模型,客户端请求服务器数据,服务端给出响应,B/S 可以看成该模式的衍生
- P2P 模式:也称为对等体系结构,每个人的电脑度可以当服务器,也可以当客户端,不单单限制于只能客户端访问服务器
5.2 DNS 协议
- Domain Name System 域名系统,也叫作域名解析协议,其作用是将域名解析成对应的 IP 地址
工作流程
- 通过域名访问网页
- 计算机会先将域名发送到一个解析域名的服务器上,该服务器有如下解析过程:
- 在其服务器上游很多服务器,能解析各种各样的域名,比如有专门解析 org、com、net 等,最重要的还有一个根域名服务器
- 域名解析(在服务器上查找 IP 地址)的过程有两种算法,迭代查询,递归查询,一般是两种查询的结合
- 本机计算机找到其中一台解析域名的服务器(可能是.com),如果没有找到对应的 IP 地址,那么就会去找根域名服务器,根域名服务器知道所有的子服务器,所以他肯定知道该域名所对应的 IP 地址在那个子服务器中,所以告诉第一次查询的服务器要他去另一台服务器上找,找到了,就将其返回给计算机,以后在有另一台计算机也通过这个域名访问,那么第一台服务器会有原来的域名IP地址的缓存,就不用去找根服务器了
-
找到了,就能找到我们要访问的服务器了
5.3 HTTP 协议
5.4 HTTPS 协议
6. HTTP 协议
6.1 概述
6.1.1 http 简介
- 协议:计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则,超文本传输协议 HTTP 是一种通信协议,它允许将超文本标记语言 HTML 文档从 Web 服务器传送到客户端的浏览器
- HTTP 协议是 Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议,其是互联网上应用最为广泛的一种网络协议,所有的 WWW 文件都必须遵守这个标准
- HTTP 是一个基于 TCP/IP 通信协议来传递数据(HTML 文件,图片文件,查询结果等)
- HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统;它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展
- HTTP 协议工作于 C/S 架构为上:浏览器作为 HTTP 客户端通过 URL 向 HTTP 服务端即 WEB 服务器发送所有请求;Web 服务器根据接收到的请求后,向客户端发送响应信息
- 在上述请求中,我们称这个客户端叫用户代理(user agent);应答的服务器上存储着(一些)资源,比如 HTML 文件和图像,我们称这个应答服务器为源服务器(origin server)
- 在用户代理和源服务器中间可能存在多个中间层,比如代理,网关,或者隧道(tunnels)
- 尽管 TCP/IP 协议是互联网上最流行的应用,HTTP 协议并没有规定必须使用它和(基于)它支持的层;事实上,HTTP 可以在任何其他互联网协议上,或者在其他网络上实现,HTTP 只假定(其下层协议提供)可靠的传输,任何能够提供这种保证的协议都可以被其使用
- 通常,由 HTTP 客户端发起一个请求,建立一个到服务器指定端口(默认是 80 端口)的 TCP 连接;HTTP 服务器则在那个端口监听客户端发送过来的请求,一旦收到请求,服务器(向客户端)发回一个状态行,比如
"HTTP/1.1 200 OK"
,和响应的消息,消息的消息体可能是请求的文件、错误消息、或者其它一些信息 - HTTP 使用 TCP 而不是 UDP 的原因在于(打开)一个网页必须传送很多数据,而 TCP 协议提供传输控制,按顺序组织数据,和错误纠正
6.1.2 http 特点
- 简单快速:客户向服务器请求服务时,只需传送请求方法和路径,请求方法常用的有 GET、HEAD、POST;每种方法规定了客户与服务器联系的类型不同;由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快
- 灵活:HTTP 允许传输任意类型的数据对象,正在传输的类型由 Content-Type 加以标记
- 短连接:短连接的含义是限制每次连接只处理一个请求,服务器处理完客户的请求,并收到客户的应答后,即断开连接,采用这种方式可以节省传输时间
- 无状态:HTTP 协议是无状态协议,无状态是指协议对于事务处理没有记忆能力,缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大;另一方面,在服务器不需要先前信息时它的应答就较快
- 支持 B/S 及 C/S 模式
6.2 URL 和 URI
6.2.1 URL
- HTTP 使用统一资源标识符(Uniform Resource Identifiers, URI)描述一个网络上的资源,来传输数据和建立连接
- URL:统一资源定位符,用来定位我们所需要资源在服务器上的位置
- URL是一种特殊类型的 URI,包含了用于查找某个资源的足够的信息
- 格式:<协议>://<主机>:<端口>/<路径>
- 协议:http (在 Internet 中可以使用多种协议,如 HTTP、FTP 等)
- 主机:域名或 IP 地址,原理一样,因为域名最终会通过 DNS 协议转化为 IP 地址,通过 IP 地址才能找到目标服务器
- 端口:在传输层需要使用的,访问目的主机的哪个端口号。
- 路径:精准的定位我们所需要的资源位置
- 锚:从“#”开始到最后,都是锚部分,锚部分也不是一个URL必须的部分
- 查询参数:从 "?" 开始到 "#" 之间的部分为查询参数部分,参数可以允许有多个参数,参数与参数之间用 "&" 作为分隔符
- 平常会省略协议和端口号,因为这些都是默认的,在访问主页时,路径也会省略,比如 www.baidu.com 这个默认进入百度的主页的完整写法为 http://www.baidu.com:80/index.html
6.2.2 URI 和 URL 的区别
- URI:即 uniform resource identifier,统一资源标识符,用来唯一的标识一个资源
- URL:即 uniform resource locator,统一资源定位器,它是一种具体的 URI,即使用 URL 作为这个唯一标识,该标识指明了如何 locate 这个资源
- 采用 URL 可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和目录等
- URL 一般由三部组成:协议 + 主机 + 端口 + 资源地址
6.3 工作流程
- 一次 HTTP 操作称为一个事务,其工作过程可分为四步:
- 客户端发出 HTTP 请求,HTTP 的工作开始,首先客户机与服务器需要建立连接(三次握手)
- 建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是 MIME 信息包括请求修饰符、客户机信息和可能的内容
- 服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是 MIME 信息包括服务器信息、实体信息和可能的内容
- 客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上,然后客户机与服务器断开连接(四次挥手)
- 如果在以上过程中的某一步出现错误,那么产生错误的信息将返回到客户端,有显示屏输出
- 对于用户来说,这些过程是由 HTTP 自己完成的,用户只要用鼠标点击,等待信息显示就可以了
- HTTP 是基于传输层的 TCP 协议,而 TCP 是一个端到端的面向连接的协议,所以 HTTP 在开始传输之前,首先需要建立 TCP 连接,而 TCP 连接的过程需要所谓的“三次握手”,在 TCP 三次握手之后,建立了 TCP 连接,此时 HTTP 就可以进行传输了
- 需要注意,在 HTTP/1.0 中,默认使用的是短连接,也就是说,浏览器和服务器每进行一次 HTTP 操作,就建立一次连接,但任务结束就中断连接;如果客户端浏览器访问的某个 HTML 或其他类型的 Web 页中包含有其他的 Web 资源,如 JavaScript 文件、图像文件、CSS 文件等;当浏览器每遇到这样一个 Web 资源,就会建立一个 HTTP 会话
- 从 HTTP/1.1 起,默认使用长连接,通过请求头
Connection:keep-alive
设置长连接,当然同时需要服务端的支持,可以在浏览器中查看多个 http 请求的 Connection ID 是否一致验证
6.4 HTTP 请求
6.4.1 HTTP 请求格式
-
HTTP 请求格式大致如图所示
- 从图中可以看出,HTTP 请求包括 4 部分:请求行、请求头、空行、请求数据(也叫请求体)
- 请求行中包括:
- 请求方法,如 GET、POST 等
- 请求 url
- http 版本
- 请求头为一对对的键值对,附带一些必要的信息,例如识别身份等
- 请求数据也叫请求体,放置需要额外传递的数据,一般 GET 请求请求体为空,因为根据标准,有的服务器会忽略 GET 请求的请求体,若需要传递参数一般通过 URL 中的查询参数传递
6.4.2 GET 请求报文举例
-
如图为搜狐官网的 GET 请求报文
第一部分:请求行
- 请求行,主要说明请求类型、请求的 URL 以及所使用的 HTTP 版本
- 该请求的请求行为
GET /http://www.sohu.com HTTP/1.1
,只不过这里显示时被分开了
第二部分:请求头部分
- 请求头跟在请求行之后,用来说明服务器要使用的附加信息
- HOST:主机名 www.solu.com,没有指定端口,使用默认端口 80
- User-Agent:用户代理,此处即为火狐浏览器
- Accept:能接受的数据类型,值为 MIME 的可能取值
- Accept-Language:表示用户希望优先想得到的版本,依次排列下去,先是中文,再是英文
- Accept-Encoding:通知服务端可以发送的数据压缩格式
- Cookie:浏览器端的一个技术,在服务器上记录用户信息,但是也会在浏览器中保存一份
- Connection:连接的方式,长连接或短连接,HTTP/1.1 默认为 keep-alive 即长连接
- Upgrade-Insecure-Requests:该指令用于让浏览器自动升级请求从 http 到 https,用于大量包含 http 资源的 http 网页直接升级到 https 而不会报错,简洁的来讲,就相当于在 http 和 https 之间起的一个过渡作用
第三部分:空行
- 请求头部后面的空行是必须的
- 即使第四部分的请求体为空,也必须有空行
第四部分:请求数据/请求体
- 请求体用于添加额外的数据,多用于 POST、PUT 等涉及修改作用的请求
- GET 请求理论上也能添加请求体但不建议,因为可能有的服务器会直接忽略 GET 请求中的请求体,因此对于 GET 请求若要传递参数建议使用 url 中的查询参数
6.4.3 POST 请求报文举例
-
POST 请求报文格式如图,其实和 GET 差不多
- 第一部分:请求行,post 请求,HTTP/1.1 版本
- 第二部分:请求头,2 - 6 行
- 第三部分:空行,第 7 行
- 第四部分:请求体,最常见的有 applicatiopn/x-www-form-urlencoded,application/json 两种类型
6.4.4 HTTP 常见请求方法
- 根据 HTTP 标准,目前为止共有 9 种 HTTP 方法
- HTTP/1.0 定义了 3 种请求方法:GET、POST 和 HEAD 方法
- HTTP/1.1 新增了 6 种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法
- GET:请求指定的页面信息,并返回实体主体
- HEAD:类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
- POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中,POST 请求可能会导致新的资源的建立和/或已有资源的修改
- PUT:从客户端向服务器传送的数据取代指定的文档的内容
- DELETE:请求服务器删除指定的页面
- CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器
- OPTIONS:允许客户端查看服务器的性能
- TRACE:回显服务器收到的请求,主要用于测试或诊断
- PATCH:是对 PUT 方法的补充,用来对已知资源进行局部更新
- RESTful Api 约定,增删改查对应 POST,DELETE,PUT/PATCH,GET
- 跨域会涉及到 OPTIONS 请求
6.4.5 补充内容
GET 和 POST 请求的区别
- GET 一般用于获取/查询资源信息,而 POST 一般用于更新资源信息
- GET 请求一般会将参数放在 url 查询参数中,而 POST 请求一般会将数据放在请求体中,如经典的 application/x-www-form-urlencoded
- 传输数据大小的限制:
- 首先明确:HTTP 协议没有对传输的数据大小进行限制,HTTP 协议规范也没有对 URL 长度进行限制,这些限制来自于具体实现
- GET:特定浏览器和服务器对 url 长度的限制,因此 GET 请求的传输数据会受到 url 长度限制
- POST:由于不是 url 传值,理论上没有限制,但实际上各个 Web 服务器都会对 post 请求的请求体大小进行限制
- 安全性:
- POST 的安全性要比 GET 的安全性高,比如通过 GET 提交数据,用户名和密码将明文出现在 URL 上
- 使用 GET 提交数据还可能会造成 Cross-site request forgery 攻击
打开一个网页需要浏览器发送多次 HTTP 请求
- 当你在浏览器输入URL http://www.cnblogs.com 的时候,浏览器发送一个 Request 去获取 http://www.cnblogs.com 的html,服务器把Response 发送回给浏览器
- 浏览器分析 Response 中的 HTML,发现其中引用了很多其他文件,比如图片,CSS文件,JS文件
- 浏览器会自动再次发送 Request 去获取图片,CSS 文件,或者 JS 文件
- 等所有的文件都下载成功后。 网页就被显示出来了
6.5 HTTP 响应
6.5.1 HTTP 响应格式
-
HTTP 响应格式如图所示
- 可以看出,HTTP 响应格式和 HTTP 请求格式基本一致,也包括 4 个部分:响应状态行、响应头/消息报头、空行、响应主体
6.5.2 HTTP 响应报文举例
-
如图
第一部分:状态行
- 状态行由 HTTP 协议版本号, 状态码, 状态消息 三部分组成
- 版本:HTTP/1.1
- 状态码:200
- 状态消息:OK (状态码基本和状态消息一一对应)
第二部分:响应头/消息报头
- 消息报头用来说明客户端要使用的一些附加信息
- Date:生成响应的日期和时间
- Content-Type:响应的 MIME 类型及编码,此处为 text/html; charset=UTF-8
第三部分:空行
- 消息报头后面的空行是必须的
第四部分:响应正文
- 服务器返回给客户端的文本信息
- 该例子中空行后面的 html 部分为响应正文,浏览器配合 Content-Type 解析对应内容
6.5.3 响应状态码
- 状态代码由三位数字组成,第一个数字定义了响应的类别,共分五种类别
- 1xx:指示信息--表示请求已接收,继续处理
- 2xx:成功--表示请求已被成功接收、理解、接受
- 3xx:重定向--要完成请求必须进行更进一步的操作
- 4xx:客户端错误--请求有语法错误或请求无法实现
- 5xx:服务器端错误--服务器未能实现合法的请求
- 常见的状态码如下 :
200 OK //客户端请求成功
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在,eg:输入了错误的URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
6.6 HTTP 工作原理
- 自此,我们总结一下 HTTP 的工作原理
- HTTP 协议定义 Web 客户端如何从 Web 服务器请求 Web 页面,以及服务器如何把 Web 页面传送给客户端,其采用了请求/响应模型,
- 客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据
- 服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据
DNS 解析步骤
- 用户键入 URL,浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址
- 解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP 连接并进行通信
HTTP 请求/响应步骤
- 建立连接:HTTP 基于 TCP,发送请求前,客户端会先与服务器建立一个 TCP 套接字连接(三次握手)
- 客户端发送 HTTP 请求:建立连接后,通过 TCP 套接字,客户端向 Web 服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据 4 部分组成
- 服务器处理请求并返回 HTTP 响应:Web 服务器解析请求,定位请求资源,服务器将资源复本写到 TCP 套接字,由客户端读取;一个响应由状态行、响应头部、空行和响应数据 4 部分组成
- 释放连接 TCP 连接:若 connection 模式为 close,则服务器主动关闭 TCP 连接,客户端被动关闭连接,释放 TCP 连接;若 connection 模式为 keepalive,则该连接会保持一段时间,在该时间内可以继续复用该 TCP 连接
- 客户端浏览器解析 HTML 内容:客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码;然后解析每一个响应头,响应头告知以下为若干字节的 HTML 文档和文档的字符集;最后客户端浏览器读取响应数据 HTML,根据 HTML 的语法对其进行格式化,并在浏览器窗口中显示
7. HTTPS 协议
7.1 HTTPS 概述
什么是 HTTPS
- HTTPS 是在 HTTP 上建立 SSL 加密层,并对传输数据进行加密,是 HTTP 协议的安全版,现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面
- HTTPS主要作用是 :
- 对数据进行加密,并建立一个信息安全通道,来保证传输过程中的数据安全
- 对网站服务器进行真实身份认证
为什么需要 HTTPS
- HTTP 通信使用明文(不加密),内容可能被窃听
- HTTP 无法证明报文的完整性,所以可能遭篡改
- HTTP 协议无法验证通信方身份,任何人都可以伪造虚假服务器欺骗用户,实现“钓鱼欺诈”,用户无法察觉
HTTPS 优势
- 数据隐私性:内容经过对称加密,每个连接生成一个唯一的加密密钥
- 数据完整性:内容传输经过完整性校验
- 身份认证:第三方无法伪造服务端(客户端)身份
7.2 HTTPS 解决方案
- HTTPS 并非是应用层的一种新协议,只是 HTTP 通信接口部分用 SSL 和 TLS 协议代替而已
- 通常,HTTP 直接和 TCP 通信,当使用 SSL 时,则演变成先和 SSL 通信,再由 SSL 和 TCP 通信,所谓 HTTPS,其实就是身披 SSL 协议这层外壳的 HTTP
-
在采用 SSL 后,HTTP 就拥有了 HTTPS 的加密、证书和完整性保护这些功能
-
HTTPS 协议的主要功能基本都依赖于 TLS/SSL 协议,TLS/SSL 的功能实现主要依赖于三类基本算法:散列函数 、对称加密、非对称加密,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性
解决内容可能被窃听的问题 - 加密
- SSL 包括了非对称加密(身份认证时使用)、对称加密(数据加密时使用)以及散列函数(加签验签时使用)
解决报文可能遭篡改问题 - 数字签名
- 这里主要是为了验证证书的完整性,即 CA 对整数加签,客户端对证书验签
-
加签:对传递的数据应用 Hash 函数获得摘要,然后对摘要使用自己的私钥进行加密即可得到签名,将签名与数据一起传递给服务端
-
验签:接受者拿到数据后执行同样的 Hash 函数获得摘要,同时使用提前得到的公钥解密数字证书获得传递过来的摘要,比对摘要是否一致,一致则说明无篡改
解决通信方身份可能被伪装的问题 - 数字证书
- 服务器的运营人员向第三方机构 CA 提交公钥、组织信息、个人信息(域名)等信息并申请认证;
- CA 通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等;
- 如信息审核通过,CA 会向申请者签发认证文件-证书。证书包含以下信息:申请者公钥、申请者的组织信息和个人信息、签发机构 CA 的信息、有效时间、证书序列号等信息的明文,同时包含一个签名;其中签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用 CA 的私钥对信息摘要进行加密,密文即签名;
- 客户端 Client 向服务器 Server 发出请求时,Server 返回证书文件
- 客户端 Client 读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后,利用对应 CA 的公钥解密签名数据,对比证书的信息摘要(即公钥验签),如果一致,则可以确认证书的合法性,即服务器的公开密钥是值得信赖的
- 客户端还会验证证书相关的域名信息、有效时间等信息; 客户端会内置信任CA的证书信息(包含公钥),如果 CA 不被信任,则找不到对应 CA的证书,证书也会被判定非法
7.3 HTTPS 工作流程
-
HTTPS 工作流程如图所示
- 首先,客户端发起 HTTPS 请求,根据 RFC2818 的规定,Client知道需要连接 Server 的 443(默认)端口
- Server 把事先配置好的公钥证书(public key certificate)返回给客户端
- Client 验证公钥证书:比如是否在有效期内,证书的用途是不是匹配Client 请求的站点,是不是在 CRL 吊销列表里面,它的上一级证书是否有效,这是一个递归的过程,直到验证到根证书(操作系统内置的Root 证书或者Client内置的Root证书)。如果验证通过则继续,不通过则显示警告信息
- Client 使用伪随机数生成器生成加密所使用的对称密钥,然后用证书的公钥加密这个对称密钥,发给 Serve
- Server 使用自己的私钥(private key)解密这个消息,得到对称密钥,至此,Client 和 Server 双方都持有了相同的对称密钥
- Server 使用对称密钥加密“明文内容A”,发送给 Client
- Client 使用对称密钥解密响应的密文,得到“明文内容A”
- Client再次发起HTTPS的请求,使用对称密钥加密请求的“明文内容B”,然后Server使用对称密钥解密密文,得到“明文内容B”