一、非可靠传输的协议——UDP
1.1 UDP的报文格式
(1)UDP长度:表示整个UDP数据包的长度(报头+载荷);
(2)校验和:用于验证UDP数据包在传输过程中有没发生比特翻转(由于各种原因导致的比特位变化,如0变为1,接收方在收到数据包后会重新进行校验和的计算,如果与UDP数据包中的校验和不同,就会丢弃这个数据包),前面所学的HTTPS中证书的数字签名本质上就是一段被加密的校验和。
1.2 UDP的特点
(1)无连接:知道对方的IP和端口号就能进行传输,不用建立连接
(2)不可靠:没有确认和重传机制,如果发送的数据报没有到达对方,UDP不会做出任何处理,对方也不知道发送方向自己发送了数据
(3)面向数据报:不能灵活控制数据读写的次数和数量
!!!但是除此之外,UDP在大部分情况下为TCP所取代的原因还有:由于UDP报头中UDP长度的大小仅有16位,只能够表示64kb的大小,对于现在来说是不够的(可能随便发送一个图片就要几个mb ),如果非要用UDP来传输的话,就需要拆分和组合数据报,非常麻烦
二、可靠传输的协议——TCP
2.1 TCP的报文格式
目前只讨论部分字段,其余字段将在后面了解到:
(1)16位源端口号/16位目的端口号:传输层的核心内容
(2)4位首部长度:4位,表示整个数据包的大小,使用4字节为单位(如4个比特位最多表示15,15x4=60字节)
(3)保留(6位):为未来可能的协议扩展或新功能预留的,目前保留位通常被设为0
(4)6位标志位:包含URG等6个字段,是TCP最核心的6个标志位
2.2 TCP的核心机制
2.2.1 保证传输可靠性的机制
这里所说的可靠性并不是说A给B发送一组数据,B一定能收到,而是尽可能的让B收到,就算B收不到,A也能知道
2.2.1.1 核心机制一——确认应答
如A给B发送一组数据,B接收到以后,会向A发送一个应答报文。
什么是应答报文?
答:应答报文也是一个TCP数据报,但是它的载荷不携带任何信息,在发送应答报文时,只需要将6位标志位中的ACK设置为1即可。
确认应答的过程是怎么样的?(图示)
但是,对于上述确认应答的过程,有没有可能A给B发了不止一个数据报,而B的应答报文发错对象了呢?如图:
为了解决这种情况,TCP引入了序号和确认序号两个字段
(1)序号主要是用在传输数据的报文中的(即载荷不为空的报文),当然在后面建立连接和关闭连接等阶段的报文也会使用。
(2)确认序号主要是用在ACK为1的应答报文或其他如(FIN + ACK)报文中的(也就是只有ACK为1的报文中的确认序号才生效)。
序号相当于对A的数据做了一个编号,而确认序号可以表示这个ACK是对特定序号的回复
在实际传输过程中,是如何对数据进行编码的呢?TCP采取的是对每个字节都进行编码,如
图:(下图表示每1000个字节为一个TCP数据包)
它的确认应答机制如下图:可以看到,确认序号的内容是将收到的数据报的载荷的最后一个字节的编号+1得到的
!!!确认序号的含义?
表示小于确认序号的数据报都已经收到了,接下来可以从序号为确认序号的序号开始发送数据报了(如确认序号为2001,表示1~1000还有1001~2000的数据包都已经收到)
引入序号之后,接收方就可以对收到的数据进行排序,确保应用程序通过socket api读取到的数据顺序是正确的 ,那么,具体的读取过程如何?
(1)TCP会在接收方安排一个接收缓冲区
(2)从网卡中读取到的数据,会先放到接收缓冲区中,后续代码调用read方法读取数据,也是从接收缓冲区读的
(3)在接收缓冲区中,收到的数据是根据序号来排序的,如果前面的数据还没到,后面的数据先到了,read就会进入阻塞,只有前面的数据到了,read才可以解除阻塞
2.2.1.2 核心机制二——超时重传
由于网络数据的传输链路复杂多样,各路由器/交换机的状态(是否繁忙)又不可知,导致数据在传输过程中会不可避免的出现丢包,为了应对可能出现的丢包,TCP引入了重传机制。
假设A给B发送了一个数据
(1)如果一定时间(即超时时间)内A还没有收到B发来的应答报文(ACK),A就会重新发送数据报给A(超时时间的阈值是动态变化的,如果这次超时了,那么阈值就会提高)
(2)如果超时次数达到一定次数,就会认为网络出现了严重故障,放弃此次传输。
这里出现的丢包状况有两种可能:对于这两种可能,A是无法分辨的,都是重发数据报
2.2.2 核心机制三——连接管理
2.2.2.1 三次握手——建立链接
(一)三次握手的过程
<1>客户端A先给服务器B发送一个SYN(同步报文),表示希望与B建立连接
<2>B收到SYN后,会发送一个ACK + SYN报文,表示已经收到A的SYN,且在B发送的SYN+ACK报文中还包含着一段序列号,用于标识B后续发送数据的起始位置(如初始序列号为5000表示B接下来发送的数据从5000开始编号)
<3>A收到B发送的ACK+SYN报文后也会给B发送一个ACK,表示已收到
(二)三次握手有什么用?
<1>确定双方的通信链路是否正常
<2>确定双方的发送能力和接收能力是否正常
<3>可以协商一些关键信息,如上面提到的序列号(表示接下来发送的数据的序号从哪里开始)
(三)三次握手过程中客户端和服务器对应的状态
2.2.2.2 四次挥手——断开连接
(一)四次挥手的过程
<1>A向B发送一个FIN报文(终止报文),表示断开此次连接
<2>B收到 A发来的FIN后 ,向A发送ACK表示收到
<3>B再发送一个FIN报文给A(触发A关闭连接)
<4>A收到 B发来的FIN后 ,也会向B发送ACK表示收到
(二)四次挥手中双方的状态
!!!在四次挥手过程中可能会发生丢包的问题,TIME_WAIT的作用之一就是为了防止最后一次发送的ACK丢包(有一定的等待时间,防止在对方还没有收到ACK就关闭连接,且刚好ACK发生丢包的情况)
2.2.3 核心机制四——滑动窗口
TCP是以牺牲效率来保证可靠性的,而滑动窗口通过批量发送一组数据可以在保证可靠性的基础上提高一些效率,如图:
相当于用原来的一份时间等待多组ACK
在A收到一个ACK后,不是继续等待剩下的ACK都到了才发下一条数据,而是直接发送下一条数据,如图:(同理,如果是3001的ACK先到了的话窗口就直接向后移动两个格子(因为后一个ACK可以涵盖前一个ACK的含义,如先收到3001,就表示1~3000所有的数据报都已经收到了))
当然,在滑动窗口中也可能发生丢包,分为两种情况
(一)ACK丢了
这种情况不用做任何处理,因为前面也说过后一个ACK可以涵盖前一个ACK的含义
(二)数据包丢了
可以看到,如果前面的数据包丢包了,就算后面的数据包到了ACK中的确认序号也还是前面丢失数据包的起始序号。
如果数据发送方连续收到3个同样的确认应答,就会进行快速重传,重新发送这部分数据。
直到主机A将1001~2000的数据包重新发送并且被接收,ACK中的确认序号才会更新。
2.2.4 核心机制五——流量控制
前面说到,滑动窗口可以在确保可靠性的前提下,批量发送一组TCP数据包,那是否批量发送的数据包越多越好呢?其实不是,如果批量发送的数据过多就无法确认可靠性了,因此TCP中引入了流量控制。
TCP支持根据接收端的处理能力, 来决定发送端的发送速度. 这个机制就叫做流量控制
那如何衡量接收端盖的处理能力呢?
答:在ACK中依赖一个字段——16位窗口大小,发送方会根据ACK中的窗口大小,动态的调整滑动窗口的窗口大小。
那16位窗口大小中的数据是怎么得到的呢?
答:在new 一个Socket对象的时候,会在操作系统内核中分配一个接收缓冲区,窗口大小的值,就是接收缓冲区中剩余空间的大小。
如果得到的窗口大小为0,怎么办?
答:
2.2.5 核心机制六——拥塞控制
流量控制是根据接收方的接收能力来控制的,但是两台主机进行通信过程中,两台主机可能并不是简单的连接,其中可能涉及到复杂的数据传输链路,如果数据链路过于繁忙,也会导致丢包,因此,拥塞控制就是根据数据链路的转发能力决定发送端的发送速度。
那么,如何衡量数据链路的转发能力?
答:通过实践来得出,如发送方先发送少量数据,如果没有出现丢包情况,就持续增大发送的数据量,如果出现丢包情况,就减少发送的数据量,动态的调整。具体的调整过程如下图:
因此,拥塞控制的工作过程可以描述为:慢启动——>指数增长——>线性增长——>出现丢包,窗口变为较小值。
2.2.6 核心特性七——延时应答
一般情况下,接收方在收到数据后会立即返回ACK,但是实际上我们可以通过延时应答来提高效率,如在前面计算窗口大小的时候,如果我们直接返回ACK也可以,但是否可能在ACK还没有到达对方的时候,接收缓冲区中的数据就又被读取了很多使剩余空间大小增大了呢?
很有可能,因此如果使用延时应答,就可以放回一个较大的窗口大小,提高了效率 。
但是,并不是所有的包都可以延时应答,一般
<1>数量限制:一般每个几个包就应答一次
<2>时间限制:超过最大延迟时间就应答一次
2.2.7 核心特性八—— 捎带应答
捎带应答是在延时应答的基础上建立的,它可以使得携带业务数据的报文和应答报文处于同一时期发送,这样一来就可以合并这两个报文了,起到提高效率得作用。
前面四次挥手过程中的FIN报文和ACK报文也后可能因为延时应答处于同一时机而被合并。
2.2.8 核心特性九——面向字节流
我们要讨论的问题其实并不是面向字节流本身,而是面向字节流所带来的问题——粘包问题, 即无法区分从哪个数据包到哪个数据包是一个完整的应用层数据包。
对于粘包问题,在TCP层面上误解,只能从应用层解决:
<1>约定包与包之间的分隔符,如以 /n 作为包的结束标记;
<2>约定包的长度,如将每个包的前4个字节用来表示数据包的长度;
在HTTP中,对于get请求,没有body,使用空行作为结束标记;对于post请求,有body,使用Content-Length记录body的长度。
2.2.9 核心特性十——异常情况的处理
在TCP中存在以下几种特殊情况:
<1>进程奔溃:和主动退出没有本质区别,都是是使进程释放,回收文件描述符表的每个资源(即调用socket的close方法),就会正常触发四次挥手(进程没了,但是TCP连接还在)
<2>主机关机(正常关机):本质上还是先杀死所有的进程,如果在关机前,四次挥手结束了,就是和<1>的情况相同;如果没有结束:
<3>主机掉电:
1.接收方掉电:
2.发送方掉电
<4>网线断开:站在接收方视角,就是发送方掉电
站在发送方视角,就是接收方掉电
标签:ACK,IP,报文,TCP,交通规则,发送,数据包,应答 From: https://blog.csdn.net/zhakakqns/article/details/144921972