目录
TCP传输的数据的控制(可靠,效率);这两者成反比。
TCP原理:
TCP对数据传输提供的管控机制,主要体现在两个方面:安全和效率。
这些机制和多线程的设计原则类似:保证数据传输安全的前提下,尽可能的提高传输效率。
说明:发送数据,接收端应该返回确认接收到的数据报的应答。
保证可靠传输的核心机制:
关键就是接受方收到消息之后,给发送方,返回一个应答报文(ACK),表示自己已经收到了。且每一个ACK都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据;下一次你从哪里开始发。
下一个:接收到的数据报,连续序号+1
隐含含义:接收端,下一个的序号,之前的数据报,全都已经接收。
如果在传输过程中,出现了丢包的情况,超时重传机制就起到了效果。
为什么会丢包?
(1)发出去的消息丢了,
- 主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达主机B;
- 如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发
(2)也有可能是ACK丢了,虽然对方收到了,但是我没有收到ACK。
此时,如果发送端超过一定的时限,没有接收到ack的应答,就回进行重传。这里一定的时限:是动态变化的,由网速有关。
因此主机B会收到很多重复数据。那么TCP协议需要能够识别出那些包是重复的包,并且把重复的丢弃掉。
TCP的去重操作。
--- 接受方收到的数据会先放到操作系统内核的“接收缓冲区”中
--- 接收缓冲区可以视为是一个内存空间,并也可以视为一个“阻塞队列”
这时候我们可以利用前面提到的序列号,就可以很容易做到去重的效果
了解:时限通过指数性增长,累计到一定的重传次数,TCP认为网络或者对端主机出现异常,强制关闭连接。
△△△很重要△△△
三次握手,四次挥手。
作用 :以并行的方式发送数据报,减少等待时间,提高效率。(叠加等待时间)(提高传输效率)
滑动窗口的本质就是在“批量的发送数据”,一次发一波数据,然后一起等一波ACK。
由于确认应答机制的存在,导致了当前每次执行一次发送操作,都需要等待上一个ACK的到达,大量时间都浪费在了等ACK中
窗口大小? = min(流量窗口大小,拥塞窗口大小)
发生丢包。
(1)ack丢了。
部分ack丢了不影响,因为可以通过后续的ack继续进行确认。
(2)数据包直接丢了。
- 当某一段报文段丢失之后,发送端会一直收到 1001 这样的ACK,就像是在提醒发送端 "我想要的是 1001" 一样;
- 如果发送端主机连续三次收到了同样一个 "1001" 这样的应答,就会将对应的数据 1001 -2000 重新发送;
- 这个时候接收端收到了 1001 之后,再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中;
这种机制被称为 "高速重发控制"(也叫 "快重传")。
接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应
流量控制的关键:就是得能衡量接收方的处理速度
如果剩余空间比较大,就认为接收方的处理能力比较强,就可以让发送方发的快一些
如果剩余空间比较小,就认为接收方的处理能力比较弱,就可以让发送方发的慢一点
接收端如何把串口大小告诉发送端呢?
TCP首部中,有一个16位窗口字段。这里就存储了窗口大小信息。
那么问题来了,16位数字最大表示65535,那么TCP窗口最大就是65535字节么?
实际上,TCP首部40字节选项中还包含了一个窗口扩大因子M,实际窗口大小是 窗口字段的值左移 M位。
背景:网络状态不明的情况下,贸然发送大量数据报,就可能网络拥塞
即,发送端在发送诗句之前,首先先根据“拥塞窗口”来探路。
- 此处引入一个概念程为拥塞窗口
- 发送开始的时候,定义拥塞窗口大小为1;
- 每次收到一个ACK应答,拥塞窗口加1;
- 每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小做比较,取较小的值作为实际发送的窗口;
<1> 刚开始的时候,取得初始窗口大小非常小
<2> 指数规律增长。初始情况下给的窗口大小太小了,可能适合更大的值
<3> 从“指数->线性”。也称为阈值,到达该值后,也就决定了啥时候,这个阈值也不是一直不变的,当每次出现丢包后,阈值就会更新为出现丢包窗口的一半。
<4> 进入线性增长
<5> 线性增长到一定程度后,就会出现丢包,一旦丢包,此时发送方就会立即让窗口变小(然后继续重复刚才的指数增长+线性增长过程)
背景:接收端返回流量窗口代表接收缓冲区可用空间的大小,去过立即返回,就不划算;
所以说:接收端返回的流量窗口,不是立即返回,而是等待一定时间,这样返回的窗口可能更大流量窗口大小是滑动窗口大小的因素之一;而滑动窗口大小有是网络吞吐量的决定因素之一
不管是客户端还是服务端,都可以是发送端,也可以接收端。
不管是客户端还是服务端,接收数据是后,返回ack应答包,可以和发送的数据报合并在一起发送给对方。
应用层需要约定统一的协议,明确包和包之间的边界;没有明确边界,就会出现粘包问题
TCP粘包指的是粘的是应用层数据报,在TCP接受缓冲区中,若干个应用层数据包混在一起了,分不出谁是谁了;在TCP的协议中,没有如同UDP一样的“报文长度”这样的字段,但有一个序号这样的字段;站在传输层的角度,TCP是一个一个报文过来的,按照序号排好放在缓冲区中;站在应用层的角度,看到的是一串连续的字节数据
注意:粘包问题不是TCP独有的问题,只要是“面向字节流”都会涉及到粘包,面向数据报的UDP就没有这个问题
---UDP和TCP的区别?以特点为基础。
TCP: UDP:
1.有连接 1.无连接
2.可靠 2.不可靠
3.面向字节流 3.面向数据报
4.缓冲区: 接收发送都有 4.缓冲区,只有接收缓冲区,以为它直管发不管丢包。
5.大小不限 5.大小受限
6.适用于可靠性比较高的场景。 6.适用于,实时性要求高,且允许少量丢包
细节,数据报 vs 字节流
数据报是网络传输的数据的基本单元,包含一个报头和数据本身,其中报头描述了数据的目的地以及和其它数据之间的关系。同一报文的不同分组可以由不同的传输路径通过通信子网。UDP基于数据报。
字节流方式指的是仅把传输中的报文看作是一个字节序列,在字节流服务中,由于没有报文边界,用户进程在某一时刻可以读或写任意数量的字节。 TCP基于字节流。
两者的区别在于TCP接收的是一堆数据,而每次取多少由主机决定;而UDP发的是数据报,客户发送多少就接收多少。
--- 基于传输层UDP协议,设计一个可靠是数据传输。或者,基于传输层UDP协议,设计一个可靠是数据传输
在应用层实现类似TCP的可靠机制;
如:引入TCP类似的字段序号;引入TCP类似的确认应答;引入TCP类似的超时重传。
引进报文确认与超时重发机制,有效改善了UDP协议下数据传输的可靠性,在特定局域网环境中,同时获得了实时高效与可靠传输的特性。在实际工程应用中,报文重发次数、重发超时时间、定时器消息周期等参数,可根据需要进行设定。
--- 如何基于UDP协议实现可靠传输?
这个问题其实就是考TCP,本质上就是在应用层基于UDP复刻TCP的机制
实现确认应答机制,每个数据收到之后,都要反馈一个ACK
实现序号/确认序号,以及实现去重
实现超时重传
实现连接管理
要想提高效率,实现滑动窗口
为了限制滑动窗口,实现流量控制/拥塞控制
实现延时应答,捎带应答,心跳机制..
--- 啥样的场景中适合使用TCP,啥用的场景中适合使用UDP?
(1)对可靠性有一定要求的时候,使用TCP(日常开发中的大多数情况,都基于TCP)
(2)如果传输的单个数据报比较长(超过64k),首选TCP
(3)啥时候使用UDP?对可靠性要求不高,对于效率的要求更高