【TCP】确认应答 与 超时重传
一. 确认应答机制
确认应答: 保障可靠传输的核心机制。
可靠传输: 不是指传输过去的数据不出错, 也不是指数据一定能传输过去,而是指发送方能够知道接收方是否接收到了数据。
确认应答的关键就是接收方收到数据后,返回给发送方一个确认应答报文 (ACK acknowledge), 表示自己已经收到数据了。
确认应答号是 接收到的最后一个字节数据的编号 + 1
A 给 B 发送了 1000B 数据,B 返回给 A 中的 ACK 中就会带有确认号 1001,表示 1001 之前的数据已经接受到了,接下来 A 应该从 1001 开始发送。
TCP 将每个字节的数据都进行了编号。即为序列号。
注意:是按照字节进行了编号,并不是按消息的条数。
每一个 ACK 都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据;下一次你从哪里开始发。
如果不使用序列号和确认应答号的话,发送发就不知道接收方是针对哪些的确认应答,不知道接收方到底接收到了哪些数据。
举个栗子:
滑稽老铁给女神发送消息:
这种情况就说不清了,使用序列号和确认号就能解决:
二. 超时重传机制
- 主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达主机B。
- 所以 A 就无法收到 B 的 ACK。
- A 等了一个特定时间间隔还没有收到B发来的确认应答,就会进行重发。
但是,主机A未收到B发来的确认应答,也可能是因为ACK丢失了,这样 A 也不能收到 ACK,也就重新发送,那么 B 就会收到了重复的数据:
因为主机B会收到很多重复数据,所以 TCP 协议需要能够识别出那些包是重复的包,并且把重复的丢弃掉。
去重:
这时候我们可以利用前面提到的序列号,就可以很容易做到去重的效果:
- 接收到的数据会被放到操作系统内核的接收缓冲区。(发送方也有发送缓冲区。)
- TCP 会根据序列号判断是否重复,如果缓冲区里面已经有这个数据了,那就直接丢弃。
- 从而能够保证上层应用程序调用 Socket API 拿到的数据一定是不重复的。
(所以我们应用层是感知不到超时重传的过程的。)
超时的时间如何确定?
- 最理想的情况下,找到一个最小的时间,保证 “确认应答一定能在这个时间内返回”。
- 但是这个时间的长短,随着网络环境的不同,是有差异的。
- 如果超时时间设的太长,会影响整体的重传效率;
- 如果超时时间设的太短,有可能会频繁发送重复的包;
TCP 为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间。
-
Linux中(BSD Unix 和 Windows 也是如此),超时以 500ms 为一个单位进行控制,每次判定超时重发的超时时间都是 500ms 的整数倍。
-
如果重发一次之后,仍然得不到应答,等待 2*500ms 后再进行重传。
-
如果仍然得不到应答,等待 4*500ms 进行重传。依次类推,以指数形式递增。
-
累计到一定的重传次数,TCP 认为网络或者对端主机出现异常,强制关闭连接。
什么时候使用 TCP ?什么时候使用 UDP ?
- 对可靠性有一定要求,日常中大多数情况都是基于 TCP。
- UDP用于对高速传输和实时性要求较高的通信领域,例如,早期的QQ,视频传输等。
- UDP 还有一个优势:天然支持广播。
好啦! 以上就是对 TCP 确认应答 与 超时重传机制的讲解,希望能帮到你 !
评论区欢迎指正 !