【JavaEE】TCP协议的十大原理保姆讲解(Transmission Control Protocol)

  • 博主简介:想进大厂的打工人
  • 博主主页:@xyk:
  • 所属专栏: JavaEE初阶

上一篇文章讲了UDP协议,那么这篇文章我来讲讲TCP协议,TCP协议相对UDP协议难一些,内容相对更多。

TCP,即Transmission Control Protocol,传输控制协议,人如其名,要对数据的传输进行一个详细的控制。
分别介绍TCP协议段格式,以及TCP的十大原理(确认应答、超时重传、连接管理、滑动窗口、流量控制、拥塞控制、延迟应答、捎带应答、面向字节流、异常情况)

TCP对数据传输提供的管控机制,主要体现在两个方面:安全和效率。这些机制和多线程的设计原则类似:保证数据传输安全的前提下,尽可能的提高传输效率。


目录

文章目录

一、TCP协议

1.1 TCP协议段格式:

1.2 TCP实现可靠性传输——确认应答机制

1.3 丢包现象——超时重传

1.4 连接管理(三次握手,四级挥手)

1.5 批量发送——滑动窗口

1.6 流量控制

1.7 拥塞控制

1.8 延时应答

1.9 捎带应答

1.10 面向字节流

1.11 异常情况

1.进程关闭 / 进程崩溃~

2.主机关机(正常流程关机)

3.主机掉电(拔电源,啪的一下,很快的)

4.网线断开

二、TCP十大核心机制小节

三、TCP 与 UDP的差别


一、TCP协议

TCP特性:

  1. 有连接
  2. 可靠传输
  3. 面向字节流
  4. 全双工

其中可靠传输是TCP存在的初心!!最核心的机制

那么TCP如何实现的可靠传输??

不是说,100%就能传过去(要求太高了),而是尽可能的传过去~~如果传不过去,发送发至少能知道自己没传过去~

核心机制,在于接收方收到了或者没有收到,都会有个应答~~

教人知识也是如此,我如果教一个同学一个知识,他没有如何应答,我就没法判断他掌握了没有~

  • 同学会了:我接着讲~~
  • 同学不会:我重新讲~~

1.1 TCP协议段格式:


1.2 TCP实现可靠性传输——确认应答机制

实现可靠性的最核心机制!!

举例说明:

假设我追女神,想约女神出来吃饭~~于是我给女神发短信~

在网络上,经常会出现,后发先至 的情况~~比如:

如果先收到了 滚,后收到了 好啊好啊~~

这样的话,我是非常高兴的~~~

为了解决上述问题,就需要针对消息进行编号!!给发送的消息分配一个“序号“,同时应答报文也给出”确认序号“

 

 真实的 TCP 数据传输也是引入了 序号 和 确认序号!!

TCP将每个字节的数据都进行了编号,即为序列号。

TCP是针对每个字节都去编号!!(并没有”一条两条消息“这样的说法)

从前往后,把每个字节分别分配一个编号~~

发送方的确认序号是一个无意义的数据

注意,确认序号的规则!!!

不是说,发送方的序号是什么,确认序号就是什么,而是取的是发送方发过来的所有数据,最后一个字节的下一个字节的序号;

确认序号 1001 的含义:

  1. < 1001 的数据,我已经收到
  2. 我接下来想向发送方索要从 1001 开始的数据

于是,接收方就可以通过 ack 的确认序号,告诉发送方哪些数据已经收到了~


为什么网络上会出现 后发先至??

举个结婚的例子:

接亲需要车队,车队的头车是新郎坐的,排在最前面

这个车队只要开出了村口,就开始放飞自我~

新郎家和新娘家,如果中间的路很远,这些车就各走各的,最后到终点集合~~

当这些车分开的时候,就很难保证到达的顺序了~~经常是头车还没到,其他的车就先到了,后发先至~~

当后面的车先到娘家,先在村口等,等车都到齐了,重新整队~~慢慢的开到终点


那么对于 TCP 来说,自身也承担了这个整队的任务~~

每个TCP会有个接收缓冲区(一块内核中的内存空间),每个 socket 都有一份自己的缓冲区的~

TCP 就可以按照序号针对收到的消息进行整队了~~(也是TCP 序号的一个重要用途)


 1.3 丢包现象——超时重传

如果中间的任何一个节点,出现了问题,都可能导致丢包~~

每个设备,都是在承担很多的转发任务的

每个设备,转发能力都是有上限的!!

某一时刻,某个设备,上面的流量达到峰值,就可能引起部分数据丢包~~ 

如果发送方在一段时间后,迟迟没收到ACK,则发送方会判定为刚才的数据丢包了!

  • 发送方就会重新再发一遍,即 超时重传
  • 大概率重新发过去是能成功的,如果又失败了,超时重传即可

其实没有收到ACK有两种情况:

  1. 数据直接丢了,接收方没收到,自然不会发ACK
  2. 接收方收到数据了,但是返回的ACK丢了

  • 发送方是区分不了这种情况的,一定会超时重传
  • 这样的话,接收方将收到重复的一个数据
  • 这很严重,要是是涉及付款的操作,重复扣款两次,那就不太好了~~

这种情况下,B会收到重复的数据,还记得TCP的序号机制吗??

  • TCP会根据发过来的数据的序号,自动去重!
  • 保证应用程序读到的数据仍然只有一份
  • 哪有什么岁月静好,是TCP在给咱们负重前行罢了

重传的数据也是有可能又丢了!!

例如丢包率为10% ==> 连续丢包两次==>10% * 10 % ==>  1%,概率很低很低了,如果还丢包,那网络出现问题的概率更大!

  • 丢包很多次 ==> 丢包率50% + ,这就太离谱了(网络大概率出现了严重故障!)

所以,TCP处理这种多个包丢失的情况,仍然会超时重传

  • 但是,每次丢包异常,超时等待时间,都会变长~~(重传的频率降低了)TCP就开始摸鱼了~
  • 如果连续丢包很多次,多半是你网络出现严重问题了,TCP将尝试重连
  • 如果重连都失效,TCP就会关闭连接,放弃此次网络通讯!

能重传就重传,实在传不了了,就关闭连接了,尽最大可能完成传输~~

确认应答,保证可靠性

超时重传,弥补丢包现象

这两个机制,是 TCP 可靠性的基石!!!


1.4 连接管理(三次握手,四级挥手)

问题:TCP 是如何实现可靠性的?

答:确认应答 + 超时重传~~   

(很多人会回答,因为TCP 的三次握手和四次挥手,这是不对的!!)

TCP 建立连接:三次握手

TCP 断开连接:四次挥手

但是,上述这两个过程,和可靠性,多少有一点点关系,仅此而已~~


三次握手:

一次握手 (handshake):指通信双方,进行一次网络交互~

三次握手表示客户端和服务器之间,通过三次交互,建立了连接关系~~各自记录对方的信息~

其中,syn 是 同步报文段,意思就是一方要向另一方,申请建立连接~~

ack 是 应答报文段,意思是接收方 收到了应答~~

  1. 客户端发出请求连接的申请 【syn】
  2. 服务器返回 【ack】 确认连接,并发送 【syn】,申请与客户端连接
  3. 客户端也返回 【ack】 确认连接

只有双方都确认了连接,关系就建立起来了,连接建立完成!!

注意~~上述过程内核自动完成,应用程序干预不了,等到连接完成了,服务器 accept 把建立好的连接从内核拿到应用程序中~~

 那么四次交互,为啥叫做三次握手???

首先你要认识这 6 个特殊的比特位,这几位默认是 0

如果设为 1,则表示特定含义

其中第二位,是 ACK,如果这一位为 1,表示 当前 TCP 数据报是一个 应答报文

其中第五位,是 SYN,如果这一位为 1,表示 当前 TCP 数据报是一个 同步报文 

第六位为1:fin报文 ==> 结束报文

如果一个 TCP 数据报,第二位和第五位都是 1,则表示当前这个报文是 SYN + ACK

  • 这就是三次握手的第二次握手发送的报文

所以,中间的两次交互合并成了一次!!!


知道了三次挥手,还要了解下,为啥要三次挥手??起到了什么效果,达成了什么目标??

三次握手,本质上是投石问路,验证了 客户端 和 服务器,各自的发送能力和接收能力是否正常!

从这个角度看,三次握手 和 可靠性,也是有关系的(但是肯定没有 确认应答 超时重传,更重要)

疑问:

上述流程中,如果两次握手行不行???四次握手行不行???

可以把中间的 syn 和 ack 拆开分别发送,同样也能达成目的,但是没有必要,会降低效率!!(封装和分用)


四次挥手:

断开连接,四次挥手~~

通信双方,各自给对方发一个 FIN (结束报文),再各自给对方返回 ACK~~

跟三次握手很像,但是有点差异

建立连接,一定是客户端主动先发起

断开连接,客户端和服务器都有可能先发起~~

就比如男生提分手和女生提分手,都是有可能的

此时,有个疑问,那么中间的两次交互不能合并吗???

三次握手中,ack 和 syn 是同一个时机触发的(都是内核来完成的,第一时间返回ack)

四次挥手中,ack 和 fin 则是不同时机触发的(fin 是应用程序代码来完成,在调用close方法才触发

一般来说,服务器那个线程是不会立马结束的,所以ack和fin分两次发

  • 但是也有个别情况,ack和fin,应答报文和结束报文是同一个数据报发送

总流程:


1.5 批量发送——滑动窗口

TCP 要保证的不仅仅是可靠性,还要效率!!!

TCP为了可靠性,牺牲了效率

  • 因为要等待应答,超时重传…

单看效率,是完全比不上UDP的

  • 但是TCP也在挽救它的效率~

A在这边花了大量的时间在等待 ACK~~

想要提高效率,就要批量发送数据了

批量发送:一次发多条数据,同时等待一个ack,既然这样一发一收的方式性能较低,那么我们一次发送多条数据,就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了)

这里就是批量发送 4 条数据,发完之后,统一等待 ack

每次收到一个ack 就立即发下一条(不是收到4个ack再发下一组),使用一份时间,等待多个ack

批量发送不是无限制发送数据,而是发送到一定程度后,等待ack

  • 发太多对方也可能受不了

而这个限制就是窗口的大小~

此时的效果就好像,窗口还是那么大,但是往后挪了一个格子,如果收到的 ack 非常快,此时这个窗口就在快速的往后滑动~~

如果批量发送的过程中,如果出现丢包怎么办??

情况一:数据包已经抵达,ACK被丢了

 这个图中,相当于一半的 ack都丢了,相当高的丢包率~~~

注意,这种情况下,啥事没有,即使丢了这么多的 ack,对于可靠性没有影响

确认序号的含义,表示该序号之前的数据都已经收到了,后一个ack,能够涵盖前一个ack

当收到 2001 这个ack 的时候,此时发送方就知道,2001之前的数据都收到了

情况二:数据包就直接丢了。

这个情况下,由于1001 - 2000这个数据丢了,所以接收方仍然再次索要 1001,不会说因为收到的是其他的序号就返回,接下来的几次的数据的 ack,继续索要 1001 这个数据!!!

A这边连续收到几个 1001 之后,就知道这个事情不简单,于是重传数据!!

当A把 1001 - 2000这个数据重传后,返回的 ack确认序号是 7001,因为2001 - 7000 这些数据已经都收到了!!!

当 1001 这个数据重传过来之后,就会补全,这个重传过程也叫做 快速重传

滑动窗口,快速重传,是在批量传输大量数据的时候,会采取的措施~~
如果你只传输一条两条,少量的,低频的操作,就不会按滑动窗口那么传输了,仍热是确认应答和超时重传!!


1.6 流量控制

也是保证可靠性的机制

滑动窗口,批量发送,窗口越大,相当于批量的数据越多,整体的速度就越快~~

但是,传输数据并非是越快越好,如果发送的太快了,瞬间把接收方的接收缓冲区给打满了,接下来继续发送,数据就会丢包,还不如发送的慢点!!

当ack为1时,ack报文此时的窗口大小字段就会生效,这里的值就是建议发送方发送的窗口大小~

直接拿接收缓冲区,剩余空间,作为窗口大小 !!

 接收方根据自己的处理能力,反向约束发送方传输速度


 1.7 拥塞控制

滑动窗口的大小 取决于 流量控制 和 拥塞控制~~

  • 流量控制:衡量了接收方的处理能力
  • 拥塞控制:衡量了传输路径的处理能力

拥塞控制 做的事情,就是衡量中间节点,传输的能力~~

通过实验的方式,找到一个合适的发送速率!!! 

开始的时候,按照一个小的速率发送

如果不丢包,就可以提高一下速率(扩大窗口大小)

如果出现丢包,则立即把速率再调小

重复上述过程~~(动态平衡)

实际窗口就是:min{拥塞窗口, 流量窗口}

  • 指数增长快速到达ssthresh(阈值)后,加法增长稳步上升(减少丢包率)
  • 丢包后,重新去做实验,并且ssthresh阈值更新(变大 / 变小 /不变)
  • 当TCP开始启动的时候,慢启动阈值等于窗口最大值;
  • 在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置回1;
     

1.8 延时应答

TCP的可靠性核心为:确认应答

  • ACK要发,但是不是立即发,而是等一小会儿再发~

但是通过刚才对TCP的了解,决定传输效率的关键因素为“窗口大小”

  • 要是你ack立马发过去,那就有数据立马发过来,那么就相当于传输过来的数据又多了,可能会导致窗口变小~

相当于说:

老师现在要检查作业,而我现在偷偷的补一点作业,过一会给老师检查,这样就不会被说啦~~

这个ack延时发送后,窗口大小大概率是变大了的,因为这个过程里,接受方一直消耗接受缓冲区里的内容~

延时应答的效果,就是通过这个延时,让接收方应用程序,趁机多消费点数据,此时反馈的 窗口大小 就会更大一点,此时发送方的速度就会快一点!

那么所有的包都可以延迟应答么?肯定也不是

  • 数量控制:每隔N个包就应答一次
  • 时间控制:超过最大延时时间就应答一次


1.9 捎带应答

在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是 "一发一收" 的。

意味着客户端给服务器说了 "How are you",服务器也会给客户端回一个 "Fine, thank you";
那么这个时候ACK就可以搭顺风车,和服务器回应的 "Fine,thank you" 一起回给客户端

此时ack 就可能稍等一会再发,就很可能和 response 合并成一个数据报!!效率更高!!

为啥四次挥手,有可能是三次挥完??同理~~捎带应答起到的效果!!


1.10 面向字节流

有一个杀机问题~~粘包问题!!(一句话相当于一个“应用层数据报”)

  • 我们分不清这三个请求都是哪到哪

定义报与报之间的分割符,这就是一个有效方案

  • 这里,我们就可以定义,说完话要加句号或者问号~

还有一个常见方案:约定数据的前4个字节(或者更多),表示整个数据报的长度

  • 这些都是应用层数据报协议的注意事项~
  • 协议里会提到报的数据格式,和报的边界

1.11 异常情况

1.进程关闭 / 进程崩溃~

进程没了,socket 是文件,随之被关闭~~虽然进程没了,但是连接还在,仍然可以继续四次挥手~

2.主机关机(正常流程关机)

先杀死所有用户进程~~
也会触发四次挥手~~如果挥完,更好

如果没挥完,比如,对方发来的 fin 过来了,没来得及 ack 就关机了~此时对端就会重传 fin,重传几次之后,发现都没有 ack,尝试重置连接,如果还不行,就直接释放连接~~

3.主机掉电(拔电源,啪的一下,很快的)

1)对端是发送方

对端就会收不到 ack => 超时重传 => 重置连接 => 释放连接

2)对端是接收方

对端是没法立即知道,你这边是还没来得及发新的数据,还是直接没了~~

TCP内置了 心跳包 保活机制~~会定期询问对方是否还在

  • 周期性
  • 如果心跳没了,挂了~~

就是说,对方是接收方,对方就会定期给我发一个心跳包(ping),我就返回一个(pong)

  • 如果每个ping,都有即使的pong,那么就说明我“没挂”,机器良好
    • 我如果在控制台输入中或者等等情况下,机器正常,就会收到ping,返回pong,这个不需要代码控制
  • 如果ping没收到pong,超时重传 ==> 重载连接 ==> 释放连接

4.网线断开

同上

  • 来不及任何的挥手操作,跟第三点是一样的

二、TCP十大核心机制小节

  1. 确认应答
  2. 超时重传
  3. 连接管理
  4. 滑动窗口
  5. 流量控制
  6. 拥塞控制
  7. 延时应答
  8. 捎带应答
  9. 面向字节流 => 粘包问题
  10. 异常处理 => 心跳包

三、TCP 与 UDP的差别

TCP 可靠传输,效率没那么高,UDP不可靠传输,效率高~

两者的不同在于应用场景的不同

  • 绝大多数情况下,都可以使用TCP
  • 但是对于一些要求高效率,对可靠性要求不高的情况下,UDP会更好
    • 例如,机房内部的内网之间的数据传输 / 分布式系统~

场景:既需要可靠性,又需要比较高的效率(LOL,CSGO,dota2....)

  • 这两种协议都不合适,而传输层协议当然不止有这两种,如果你感兴趣的话,可以去了解哪些协议更适合处理这样的场景

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
非常感谢您的提问!JavaEE大作业是一个非常重要的项目,因此在完成该项目之前,您需要掌握一些基本的知识和技能。以下是一些保姆级教程,以帮助您顺利完成JavaEE大作业。 1. JavaEE基础知识 在开始编写JavaEE大作业之前,您需要掌握JavaEE基础知识。这包括Java基础、Servlet、JSP、JDBC、JavaBean等。您可以通过一些在线教程或书籍来学习这些知识。 2. 数据库设计与操作 JavaEE大作业通常需要与数据库交互,因此您需要掌握数据库设计和操作的基本知识。您可以学习SQL语言、MySQL数据库、Oracle数据库等。 3. Spring框架 Spring框架是一种流行的JavaEE框架,它提供了很多功能和工具,可以帮助您快速开发JavaEE应用程序。您可以学习Spring框架的基本知识,如Spring MVC、Spring Boot、Spring Security等。 4. 前端技术 JavaEE大作业通常需要开发一个漂亮的用户界面,因此您需要掌握一些前端技术。您可以学习HTML、CSS、JavaScript、jQuery等技术,以及一些流行的前端框架,如Angular、React等。 5. 项目管理工具 在开发JavaEE大作业时,您需要使用一些项目管理工具,如Maven、Gradle等。这些工具可以帮助您管理项目依赖关系、构建和部署项目等。 以上是一些基本的保姆级教程,以帮助您顺利完成JavaEE大作业。当然,这只是一个大概的指导,具体还需要根据您的项目需求和实际情况来进行学习和实践。祝您成功!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值