相比于 UDP 来说,TCP 的主要特性是三个:有连接、可靠、面向数据流。所谓的“有连接”指的是 TCP 中的连接管理机制,也就是著名的三次握手和四次挥手,就像打电话一样,想要正常的交流,必须先和对方建立起连接,这就是所谓的“有连接”,而面向数据流的机制咱们以后再讲,我们今天要讨论的主题是:TCP 是如何保证可靠性的?

TCP 之所以能保证可靠性,主要是通过以下 6 个手段:

  1. 校验和
  2. 确认应答
  3. 超时重传
  4. 流量控制
  5. 拥塞控制
  6. 丢弃重复数据

接下来,我们详细来看这几种手段的具体实现。

1.校验和

TCP 协议的数据格式如下图所示:



(图片来源:许许如生xxrs)

从上图可以看出“校验和”是保存在 TCP 首部中的一个数据,TCP 的发送端和接收端会采用相同的算法,根据发送的数据计算出一个 16 位的校验和,并且校验和会连同数据一起发送给接收端。

接收端在得到数据之后,会根据接收的数据生成一个新的校验和,然后用新的校验和与传递过来的校验和做对比,如果校验和相同,那么说明数据在传递过程中没有发生任何改变,是一个有效的数据,反之则为无效数据,舍弃即可。

校验和基本算法

TCP/UDP/IP 等协议的校验和算法都是相同的,采用的都是将数据流视为 16 位整数流进行重复叠加计算。为了计算检验和,首先把检验和字段置为 0,然后,对有效数据范围内中每个 16 位进行二进制反码求和,结果存在检验和字段中,如果数据长度为奇数则补一字节 0。当收到数据后,同样对有效数据范围中每个 16 位数进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中没有发生任何差错,那么接收方计算的结果应该为全 0 或全 1(具体看实现了,本质一样) 。如果结果不是全 0 或全 1,那么表示数据错误。

2.确认应答

确认应答机制是保证消息传递可靠性的关键手段,也是几乎所有消息中间件(MQ)中,最常用的技术之一,比如主流的消息中间件 RabbitMQ、Kafka、RocketMQ 中都有确认应答机制,也就是我们常说的 ACK(ACKnowledge Character,确认字符)。

确认应答机制是 TCP 中,保证消息可靠性的核心机制。怎么才能确认你发的消息对方一定收到了呢?最有效的手段无疑是对方告诉你,它已经收到了,这就是确认应答。

确认应答的流程如下图所示:

3.超时重传

消息在确认应答的过程中可能会出现两个问题:第一,消息在发送的时候丢失了,第二,消息在确认应答时丢失了,如下图所示:



显然,即使有了确认应答机制也保证不了消息不丢失,那怎么办呢?

消息丢了没关系,发送端在确认了消息丢失之后,再补偿一个同样的消息给接收端不就解决了?这就是超时重传机制。

巧妙的超时重传机制

TCP 的超时重传机制在设计上也非常巧妙,它为了保证消息在任何环境中,都能高效的通讯,所以 TCP 采用的是“动态时间”的超时重传机制。

比如第一次如果消息丢了,那么发送端会在 500ms 之后再发送一个消息,如果发送的第二个消息也丢了,那么发送端会在 1000ms 之后再发送一个消息,如果第三个消息也丢了,那么它会在 2000ms 之后再发送一个消息,如果累计了一定的次数,消息还没有成功的发送,那么 TCP 会认为对方主机存在异常,会强制关闭连接,这就是 TCP 超时重传的主要执行流程。

4.流量控制

接收端处理数据的速度是有限的,如果发送端发的太快,那么就会导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应。

因此 TCP 会根据接收端的处理情况,动态调整发送数据的大小,这个机制就叫流量控制(Flow Control)。

5.拥塞控制

拥塞控制指的是 TCP 会根据当前网络的情况,动态的控制发送数据的多少,以适合的速度来传递数据。

想象一下,如果 TCP 在不清楚网络情况的环境下,贸然的发送大量的数据给接收端,这样就会导致更多的丢包及超时重传,从而引起一系列的连锁反应,导致数据传递变慢。

TCP 采取的是“慢启动”机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据,这就是拥塞控制机制。

如果传递的数据多了,出现了大量的丢包,那么 TCP 会将发送的数据量调小,然后再尝试慢慢的增加发送的数据量,通过这种动态发送数据包的形式,来实现适合当前网速的数据传递,这就是 TCP 拥塞控制的具体实现。

6.丢弃重复数据

通过前面的知识我们知道,在确认应答时,由于确认应答消息的丢失,那么接收方可能会收到发送方的重复数据,如下图所示:



而此时对于业务方来说,只需要一个数据就可以了,所以 TCP 还有一个机制,丢弃重复数据的机制,这样就能保证业务方接收到的数据是正确的了。

TCP 会给每一个发送的包上加上一个编号,如果接收到了编号相同的数据包,那么就说明接收端得到了重复的包,丢弃即可。

总结

TCP 保证可靠性的主要手段有 6 个:校验和、确认应答、超时重传、流量控制、拥塞控制、丢弃重复数据。其中流量控制和拥塞控制很容易搞混,我们要清楚的知道,流量控制是针对接收端接收能力的控制机制,而拥塞控制是针对当前网络的控制机制,所以千万不要搞混了。

参考 & 鸣谢

blog.csdn.net/namelcx/article/details/6866720

是非审之于己,毁誉听之于人,得失安之于数。

公众号:Java面试真题解析

面试合集:https://gitee.com/mydb/interview

面试突击69:TCP 可靠吗?为什么?的更多相关文章

  1. 计算机网络传输层之TCP可靠传输

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105524592 学习课程:<2019王道考研计算机网络> 学习目的 ...

  2. 计算机网络(9)-----TCP可靠传输的实现

    TCP可靠传输的实现 以字节为单位的滑动窗口 滑动窗口的滑动是以字节为单位的,发送方A和接收方B在TCP三次握手的前两次握手时协商好了发送窗口和接受窗口的大小,发送方A根据B发送来的确认连接报文中标明 ...

  3. TCP可靠传输的实现

    TCP可靠传输的实现 1.概述      为方便描述可靠传输原理,假定数据传输只在一个方向上进行,即A发送数据,B给出确认 2.以字节为单位的滑动窗口      TCP的滑动窗口是以字节为单位的.为了 ...

  4. TCP可靠数据传输

    TCP可靠数据传输   在TCP在IP不可靠的尽力而为的服务之上,创建了一条可靠数据传输服务(reliable data transfer service).TCP提供的可靠数据传输的方法涉及到可靠数 ...

  5. TCP可靠传输及流量控制实现原理

    一.为什么TCP是可靠传输? 1. 停止等待协议 通过确认与超时重传机制实现可靠传输 在发送完一个分组后,必须暂时保留已发送的分组的副本. 分组和确认分组都必须进行编号. 超时计时器的重传时间应当比数 ...

  6. 计算机网络概述 传输层 TCP可靠传输的实现

    TCP可靠传输的实现 TCP的可靠性表现在:它向应用层提供的数据是 无差错的.有序的.无丢失的,简单的说就是:TCP最终递交给应用层的数据和发送者发送的数据是一模一样的. TCP采用了流量控制.拥塞控 ...

  7. 运输层6——TCP可靠传输的实现

    目录 1. 以字节为单位的滑动窗口 2. 超时重传时间的选择 写在前面:本文章是针对<计算机网络第七版>的学习笔记 运输层1--运输层协议概述 运输层2--用户数据报协议UDP 运输层3- ...

  8. 运输层4——TCP可靠运输的工作原理

    目录 1. 停止等待协议 写在前面:本文章是针对<计算机网络第七版>的学习笔记 运输层1--运输层协议概述 运输层2--用户数据报协议UDP 运输层3--传输控制协议TCP概述 运输层4- ...

  9. 《【面试突击】— Redis篇》--Redis都有哪些数据类型?分别在哪些场景下使用比较合适?

    能坚持别人不能坚持的,才能拥有别人不能拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>--Redis都有哪些数据类型?分别在哪些场景下使用 ...

随机推荐

  1. 让 API 测试变的简单。

    做开发已经四年有余了,之前在接口测试的时候最开始用的自己写的测试类进行测试,后来接触到了 postman 和 swagger ,虽然用起来比自己写的强太多了,但是总觉得差点事儿. 一方面是 postm ...

  2. Java注解Annotaton

    1.三种基本的Annotaton @Override : 限定某个方法,是重写父类方法 , 该注解只能用于方法 @Deprecated : 用于表示某个程序元素 ( 类 , 方法等 ) 已过时 @Su ...

  3. 132_Power BI之建模必备要素&Power Query之数据表字段名称管理

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 近段时间比较忙,也没有看到很好的DAX素材,很久没有更新文章了,刚好有时间就来凑个热闹. 今天主题是Power ...

  4. 「ABC 249Ex」Dye Color

    考虑停时定理. 初始势能为 \(\sum \Phi(cnt_i)\),末势能为 \(\Phi(n)\),我们希望构造这样一个 \(\Phi:Z\to Z\) 函数,使得每一次操作期望势能变化量为常数. ...

  5. SpringSecurity简单入门

    1.简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spr ...

  6. MySql实例关于ifnull,count,case when,group by(转力扣简单)

    给定表 customer ,里面保存了所有客户信息和他们的推荐人. id   | name | referee_id|+------+------+-----------+|    1 | Will ...

  7. JDK1.7HashMap源码分析

       1.1首先HashMap中的Hash(哈希)是什么? Hash也称散列,哈希,对应的英文都是Hash.基本原理就是把任意长度的输入通过Hash算法变成固定长度的输出,这个映射的规则就是对应的Ha ...

  8. Python数据分析--Numpy常用函数介绍(6)--Numpy中矩阵和通用函数

    在NumPy中,矩阵是 ndarray 的子类,与数学概念中的矩阵一样,NumPy中的矩阵也是二维的,可以使用 mat . matrix 以及 bmat 函数来创建矩阵. 一.创建矩阵 mat 函数创 ...

  9. 001 手把手用Git,Git从入门到上传本地项目到Github,看这篇就够了

    安装git 下载Git 下载好后,一路next即可 安装好后,打开Git bash,进行配置 首先配置自己的身份 git config --global user.name "Name&qu ...

  10. 技术分享 | Appium 用例录制

    原文链接 下载及安装 下载地址: https://github.com/appium/appium-desktop/releases 下载对应系统的 Appium 版本,安装完成之后,点击 " ...