【web】TCP/UDP协议详解(字节二面:TCP三次握手、四次挥手)

简介: 本文介绍了计算机网络UDP/TCP协议格式和特点、重点介绍保证TCP可靠性的 确认应答机制(数据编码+超时重传)、连接管理机制(TCP三次握手、四次挥手)、流量控制机制、拥塞控制机制、快重传、延时应答、捎带应答机制等。

【大家好,我是爱干饭的猿,本文介绍了计算机网络UDP/TCP协议格式和特点、重点介绍保证TCP可靠性的 确认应答机制(数据编码+超时重传)、连接管理机制(TCP三次握手、四次挥手)流量控制机制、拥塞控制机制、快重传、延时应答、捎带应答机制等。

后续会继续分享网络层IP协议及其他重要知识点总结,如果喜欢这篇文章,点个赞👍,关注一下吧】

上一篇文章:《【web】计算机网络编程(重点:UDP数据报/TCP流套接字编程)》


🤞目录🤞

💖1. UDP协议(User Datagram Protocol)

1.1 UDP协议数据报格式

1.2 UDP 发送接收数据过程

1. 发送端

2. 接收端

1.3 UDP 的特点

💖2. TCP协议(Transmission Control Protocol)

2.1 TCP协议段格式

2.2 TCP 的可靠性

2.3 TCP 做了哪些机制来保证可靠性

1. 确认应答机制(数据编码机制 + 超时重传机制)

2. 超时重传机制

3. 连接管理机制(三次握手 & 四次挥手)*重点*

4. 流量控制机制(滑动窗口机制)

5. 拥塞控制机制

6. 快重传机制(效率机制)

7. 延迟应答(效率机制)

8. 捎带应答(效率机制)

2.4 TCP 的特点

2.5 TCP的粘包问题

2.5 TCP异常情况

💖3. TCP/UDP对比


传输层重点协议TCP/UDP:负责数据能够从发送端传输接收端。

🚅1. UDP协议(User Datagram Protocol)

职责:在网络层的基础之上,实现进程to 进程的通信。

1.1 UDP协议数据报格式

UDP协议的包头(header)信息:UDP添加的封装(解包、分用)

image.gif编辑

1. UDP 包头定长8字节:容易做解包

2. 源端口+目的端口:则用作分用 | 进程 to 进程

3. 16位UDP长度:表示整个数据报(UDP首部+UDP数据)的最大长度

4. UDP校验和(checksum):为防止传输数据错误,类似于hash算法

       发送端:hash(有效数据) => 得到 h1

       接收端:hash(有效数据) => 得到 h2

       如果 h1 != h2,数据出错,丢弃数据

       如果 h1 == h2,大概率认为数据还是源数据

1.2 UDP 发送接收数据过程

1. 发送端

1. 填充端口

2. 计算长度,填充包头UDP长度

3. 计算校验和checksum,填充校验和checksum

4. 立即将数据交给网络层

注意:UDP协议栈内部没有发送缓存区

2. 接收端

1. 从网络层接收数据

2. 通过计算校验和,检查数据是否出错,如果数据出错,丢弃数据

3. 如果数据没有出错,根据自己内部维护的 Map<port, pid>,找到端口对应的接收进程。如果找不到进程,直接丢弃

4. 看对应的进程是否准备好一块内存,如果暂时没有,需要在接收缓存区暂时保存一会

5. 把数据复制到对应的内存空间 byte[] buf

1.3 UDP 的特点

UDP传输的过程类似于寄信

1. 无连接

知道对端的IP和端口号就直接进行传输,不需要建立连接

2. 不可靠

没有任何安全机制,发送端发送数据报以后,如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息

3. 面向数据报文

应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并

4. 缓冲区

UDP只有接收缓冲区,没有发送缓冲区

UDP的socket既能读,也能写,这个概念叫做 全双工

5. 大小受限

UDP协议首部中有一个16位的最大长度。也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部)

6. socket.send(); 方法返回了,代表什么意思?

代表数据已经发送到网络中,不知道对方主机或者进程是否收到。


🚅2. TCP协议(Transmission Control Protocol)

职责:在网络层的基础之上,实现进程to 进程的通信。

2.1 TCP协议段格式

TCP包头:用于解包,分用

image.gif编辑

1. 源/目的端口号:表示数据是从哪个进程来,到哪个进程去;

2. 32位序号/32位确认号:下面详细介绍

3. 4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最大长度是 15 * 4 = 60

4. 6位标志位:

       URG:紧急指针是否有效(配合16位紧急指针使用)

       ACK:确认号是否有效

       PSH:PSH=0允许TCP把收到的数据暂存一段时间,集齐一定数量再给应用层

       RST:重置连接、复位连接。无论何时一个报文段发往基准的连接(referenced connection)出现错误,TCP都会发出一个复位报文段(这里提到的“基准的连接”是指由目的IP地址和目的端口号以及源IP地址和源端口号指明的连接。

       SYN:(synchronize)请求建立连接;我们把携带SYN标识的称为同步报文段

       FIN:通知对方,本端要关闭了(四次挥手),我们称携带FIN标识的为结束报文段

5. 16位窗口大小

6. 16位校验和:发送端填充,CRC校验。接收端校验不通过,则认为数据有问题。此处的检验和不光包含TCP首部,也包含TCP数据部分。

7. 16位紧急指针:标识哪部分数据是紧急数据;

8. 40字节头部选项:暂时忽略;

2.2 TCP 的可靠性

TCP 如何保证可靠性?

1. TCP 尽自己最大的努力,将数据发送给对方

2. 如果真遇到发送不过去的情况,TCP 至少会告诉发送进程,数据发送失败

3. 保证不会收到错误的数据(通过校验和checksum)

4. TCP 保证收到的数据一定是有序的

5. TCP 会根据对方的接收能力和网络线路的承载能力,进行流量控制

2.3 TCP 做了哪些机制来保证可靠性

1. 确认应答机制(数据编码机制 + 超时重传机制)

确认应答机制:接收方(对方的TCP)有责任对接收到的数据进行(acknowledge)应答。

如果同时收到多份数据,如何知道应答的是哪部分数据,所有有了数据编码机制

对数据进行编号:序列号(sequence number)SN

image.gif编辑

32位序列号:携带本次发送数据时的数据编码,每个字节占用一个序号

32位确认序列号:填写下一次期望收到的第一个字节的序号

序号:本次发送数据的第一个字节的序号

比如:发送数据为 [abcd] [efg],则第一次发送的序列号SN为1,第二次发送的序列号SN为5

确认段(segment):一份数据即可以起到发送数据的角色,也可以起到确认的角色

发送:(SN + 携带数据)携带有数据,填写正确的SN,就是发送segment

确认:(ack + ASN)标志位ack置1.代表起到了确认的作用。需要填写确认序列号(ASN)。

2. 超时重传机制

当我发送了一份数据,没有收到应答时,可能发生了什么?

可能情况:

1.对方没有收到数据

2.对方收到了,并且应答了,但应答没有发送过来

解决方案:真的遇到没有收到应答

1. 不应该无限期的等待下去(超时timeout机制)

2. 重新发送数据(超时重传机制)!!

image.gif编辑

主机B第一次收到数据,无影响

image.gif编辑

主机B收到过2次1~1000,所以主机B可以根据数据中的序号检查进行去重操作。

TCP的发送端不用关心超时没有收到应答的原因是什么,采用统一的超时重传机制即可。如果接收端真的收到了重复的数据,直接丢弃即可。

a. 超时重传次数是无限制的么?

会有一定的上限!! 达到上限,发送方(TCP)认为本次数据线路出现重大问题了

1.TCP关闭本次连接

2.TCP会通知进程(在Java 中,采用异常方式IOException)

3.TCP会发送一个reset segment出去(RST 置为1)

b. 关于超时时间的设置

一般这个时间不是一个固定的长度,大多数是逐步变长

10s ->20s -> 40s -> 80s

站在进程角度思考,向一个有问题的TCP线路中发送数据,请问多久之后,“我(进程)”知道线路有问题了10 +20 +40 + 80s之后,发现线路有问题

c. 并且只有发送方知道线路可能有问题

作为TCP的发送方,经过一段时间之后,是可以知道线路有问题的!

作为TCP的接收方,无法得到线路有问题的(无法确认对方是没有数据发送还是发送失败了)

3. 连接管理机制(三次握手 & 四次挥手)*重点*

a. 连接的概念

image.gif编辑

b. 为什么TCP要设计建立连接。

1. 必须确认对方存在,才能“可靠”地传输

2. 交换一些必要的数据SN不是直接从1开始的,会双方各自随机生成,随后需要交换

c. 建立连接(三次握手)

在正式通信之前,需要一个建立连接的阶段

1)确认对方在线

2) “同步(synchronize)”一些基本信息

【建立连接阶段】【正式通信】【断开连接阶段】

image.gif编辑

segment的种类:发送segment、确认segment、同步信息(握手阶段使用) segment、挥手segment

多个职责可以同时存在于一个segment 中

如图:2和3基本是同一时间发生的,TCP的segment可以既承载发送数据,又承载应答的职责

所有TCP建立连接需要三次握手,两次握手建立不了连接,四次握手降低性能。

image.gif编辑

image.gif编辑

简化:

image.gif编辑

image.gif编辑

c. 断开连接(四次挥手)

标志位是fin

1. 主动断开方不一定是主动连接方

2. 可以合并,但并不是必须合并

断开连接可能分三种情况:

A. 主动连接方 断开连接,被动连接方收到后也断开连接(三次挥手)

B. 主动连接方 断开连接,被动连接方收到后过了一段时间断开连接(四次挥手)

C. 主动连接方和 和 被动连接方同时断开连接 (同时挥手)

image.gif编辑

image.gif编辑

服务器上如果出现大量的CLOSE_WAIT状态

1. CLOSE_WAIT:出现在挥手阶段

2. CLOSE_WAIT:出现在被动关闭方这一层

3. CLOSE_WAIT:对方进程要求关闭连接,但我方进程还没要求关闭连接

进一步判断,通过检查我们的代码中是否漏写了socket.close()操作了

为什么要有一个状态TIME_WAIT,不能直接走到CLOSED状态么?

1. TIME_WAIT 出现在主动连接方

2. TCP协议内部怎么区分连接的?通过五元组信息

当一个连接关闭之后,如果之前释放,则五元组信息可能被再次使用。此时,当收到发给这条连接的数据时不知道数据是给老的还是新的

3. 防止最后一个ack 丢失,对方重新发送

为什么是TIME_WAIT的时间是2MSL?

MSL: Maximum Segment Live

1. MSL是TCP报文的最大生存时间,因此TIME_WAIT持续存在2MSL的话,就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启,可能会收到来自上一个进程的迟到的数据,但是这种数据很可能是错误的); ·

2. 同时也是在理论上保证最后一个报文可靠到达(假设最后一个ACK丢失,那么服务器会再重发一个FIN,这时虽然客户端的进程不在了,但是TCP连接还在,仍然可以重发LAST_ACK) ;

TCP还提供了一种异常关闭连接的方式(了解)

收到了reset segment之后,TCP直接关闭连接。进程收到一个异常!

4. 流量控制机制(滑动窗口机制)

接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应。因此TCP支持根据接收端的处理能力,来决定发送端的发送速度。这个机制就叫做流量控制(FlowControl)

1. 减少无用功

2. 根据对方的接收能力 or 线路的承载能力 控制发送数据的多少

3. 接收能力:接收窗口(receive window)在包头 16位窗口大小

TCP协议栈每次发送segment,都会携带当前的接收窗口大小!

发送方利用 滑动窗口机制 进行发生量的控制。

image.gif编辑

    • 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 "窗口大小" 字段,通过ACK端通知发 送端;
    • 窗口大小字段越大,说明网络的吞吐量越高;
    • 接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端;
    • 发送端接受到这个窗口之后,就会减慢自己的发送速度;
    • 如果接收端缓冲区满了,就会将窗口置为0;
    • 这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。

    5. 拥塞控制机制

    1.如何得知当前网络的承载能力——拥塞窗口

    2. 发送量(发送窗口) = f(拥塞窗口,接收窗口)     取两者较小的

    3. 同样按照滑动窗口机制进行控制

    a. 如何得知当前网络的承载能力

    采用一个算法推算出拥塞窗口

    image.gif编辑

    1. 慢开始 + 快增长,慢开始,一开始 cwud 很小 cwnd = 1,在增长阶段,成指数增长cwnd = cwnd * 2,到达一个阈值(yu)后,一次 cwnd + 2

    2. 如果遇到网络堵塞,单位时间重传次数超过一定值,(像老鼠一样胆小),先会计算一个新的阈值(ssthresh) ssthresh = cwnd / 2,然后cwnd = 1。

    TCP拥塞控制这样的过程,就类似 热恋的感觉(博主单身狗)

    6. 快重传机制(效率机制)

    image.gif编辑

    当某一段报文段丢失之后,发送端会一直收到 1001 这样的ACK,就像是在提醒发送端 "我想 要的是 1001" 一样;

    如果发送端主机连续三次收到了同样一个 "1001" 这样的应答,就会将对应的数据 1001 - 2000 重新发送

    这个时候接收端收到了 1001 之后,再次返回的ACK就是7001了(因为2001 - 7000)接收端 其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中;

    7. 延迟应答(效率机制)

    如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能比较小。所以如果接收端稍微等一会再应答,比如等待200ms再应答,那么这个时候返回的窗口大小就是1M;提升效率。

    那么所有的包都可以延迟应答么?

    肯定也不是;

    数量限制:每隔N个包就应答一次;

    时间限制:超过最大延迟时间就应答一次;

    8. 捎带应答(效率机制)

    在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是 "一发一收" 的。意味着客户 端给服务器说了 "How are you",服务器也会给客户端回一个 "Fine, thank you";

    那么这个时候ACK就可以搭顺风车,和服务器回应的 "Fine,thank you" 一起回给客户端

    2.4 TCP 的特点

    1. 有链接

    2. 可靠性

    3. 面向字节流

    4. 有接收缓冲区,有发送缓冲区

    5. 大小不受限

    2.5 TCP的粘包问题

    首先要明确,粘包问题中的 "包" ,是指的应用层的数据包。 在TCP的协议头中,没有如同UDP一样的 "报文长度" 这样的字段,但是有一个序号这样的字 段。 站在传输层的角度,TCP是一个一个报文过来的。按照序号排好序放在缓冲区中。 站在应用层的角度,看到的只是一串连续的字节数据。 那么应用程序看到了这么一连串的字节数据,就不知道从哪个部分开始到哪个部分,是一个 完整的应用层数据包。

    那么如何避免粘包问题呢?归根结底就是一句话,明确两个包之间的边界

    对于定长的包,保证每次都按固定大小读取即可;

    对于变长的包,可以在包头的位置,约定一个包总长度的字段,从而就知道了包的结束位 置;

    对于变长的包,还可以在包和包之间使用明确的分隔符(应用层协议,是程序猿自己来定 的,只要保证分隔符不和正文冲突即可);

    思考:对于UDP协议来说,是否也存在 "粘包问题" 呢?

    对于UDP,如果还没有上层交付数据,UDP的报文长度仍然在。同时,UDP是一个一个把数据交付给应用层。就有很明确的数据边界。

    站在应用层的站在应用层的角度,使用UDP的时候,要么收到完整的UDP报文,要么不收。 不会出现"半个"的情况。

    所以UDP 没有粘包问题。

    2.5 TCP异常情况

    A.直接使用任务管理器关闭一个进程,请问被这个进程持有的连接会怎么办?

    虽然进程不会执行关闭操作,但OS会执行四次挥手的正常关闭

    B.点击重启,运行着的进程管理的连接会怎么办?

    OS会执行四次挥手的正常关闭点击关机,同样道理

    C.断电关闭电脑,进程持有的连接会怎么办?

    什么都不会发生。 我们这侧的内存中的数据没有了,所以连接从我们这侧,认为已经不存在了(没有走任何关闭流程)连接的另一侧,不知道发生了什么。

    D. 对方怎么就能知道连接出问题了?

    当对方有写操作时,由于多次重试失败,会发现问题(但区分不了是对端的问题还是线路的问题)这个感受不是立即的 当对方只有读操作时,永远发现不了出问题了。

    E.我们应该如何进下操作,才能必然永远维护着“死连接”?

    1. 会给读增加一个超时时间(1天)

    2. 定期给对方发消息,报平安(heartbeat 心跳包)


    🚅3. TCP/UDP对比

    TCP/UDP的socket都既能读,也能写,这个概念叫做 全双工

    我们说了TCP是可靠连接,那么是不是TCP一定就优于UDP呢?

    TCP和UDP之间的优点和缺点,不能简单,绝对的进行比较TCP用于可靠传输的情况,应用于文件传输,重要状态更新等场景;

    UDP用于对高速传输和实时性要求较高的通信领域,例如,早期的QQ,视频传输等。另外UDP可以用于广播;

    TCP:一对一

    UDP:一对多


    分享到此,感谢大家观看!!!

    如果你喜欢这篇文章,请点赞关注吧,或者如果你对文章有什么困惑,可以私信我。

    🏓🏓🏓

    相关实践学习
    深入解析Docker容器化技术
    Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
    相关文章
    |
    23天前
    |
    网络协议 安全 网络安全
    什么是TCP/UDP/HTTP?它们如何影响你的内网穿透体验?
    数据的传输离不开各种协议,它们就像现实世界中的交通规则,规定了数据如何打包、寻址、传输和接收。对于使用内网穿透的用户来说,理解TCP、UDP和HTTP这些基础协议的特点,能帮助你更好地理解其性能表现,并选择最适合的配置方案。
    |
    3月前
    |
    网络协议 安全 网络安全
    详细阐述 TCP、UDP、ICMPv4 和 ICMPv6 协议-以及防火墙端口原理优雅草卓伊凡
    详细阐述 TCP、UDP、ICMPv4 和 ICMPv6 协议-以及防火墙端口原理优雅草卓伊凡
    301 2
    |
    3月前
    |
    网络协议 开发者
    探讨UDP协议中connect函数的作用及影响
    总结来看,虽然UDP是无连接的,`connect()` 函数的使用在UDP编程中是一种可选的技术,它可以带来编程上的便利和某些性能上的改进,同时它改变的是程序逻辑上的行为,而非UDP协议本身的无连接特性。在实际应用中,根据通信模式和需求的不同,开发者可以根据情况选择是否调用 `connect()` 函数。
    158 8
    |
    5月前
    |
    监控 网络协议 视频直播
    UDP协议(特点与应用场景)
    UDP(用户数据报协议)是传输层的一种无连接协议,具有简单高效、低延迟的特点。其主要特点包括:无连接(无需握手)、不可靠传输(不保证数据完整性)、面向数据报(独立传输)。尽管UDP不如TCP可靠,但在实时通信(如语音通话、视频会议)、在线游戏、多媒体流媒体(如直播、点播)及网络监控等领域广泛应用,满足了对速度和实时性要求较高的需求。
    756 19
    |
    6月前
    |
    网络协议
    为何UDP协议不可靠?DNS为何选择UDP?
    总的来说,UDP和TCP各有优势,选择哪种协议取决于应用的具体需求。UDP可能不如TCP可靠,但其简单、快速的特性使其在某些场景下成为更好的选择。而DNS就是这样的一个例子,它利用了UDP的优势,以实现快速、高效的名字解析服务。
    318 14
    |
    6月前
    |
    网络协议 Java 开发工具
    全平台开源即时通讯IM框架MobileIMSDK:7端+TCP/UDP/WebSocket协议,鸿蒙NEXT端已发布,5.7K Stars
    全平台开源即时通讯IM框架MobileIMSDK:7端+TCP/UDP/WebSocket协议,鸿蒙NEXT端已发布,5.7K Stars
    325 1
    |
    9月前
    |
    缓存 网络协议
    Jmeter如何对UDP协议进行测试?
    `jmeter-plugins`是JMeter的插件管理器,用于管理和组织所有插件。访问[官网](https://jmeter-plugins.org/install/Install/)下载并放置于`lib/ext`目录下,重启JMeter后可在“选项”中看到插件管理器。
    256 1
    Jmeter如何对UDP协议进行测试?
    |
    9月前
    |
    缓存 网络协议 前端开发
    Web 性能优化|了解 HTTP 协议后才能理解的预加载
    本文旨在探讨和分享多种预加载技术及其在提升网站性能、优化用户体验方面的应用。
    Web 性能优化|了解 HTTP 协议后才能理解的预加载
    |
    10月前
    |
    XML JSON 算法
    【JavaEE】——自定义协议方案、UDP协议
    自定义协议,序列化,xml方案,json方案,protobuffer方案,UDP协议,校验和,比特翻转,CRC算法,md5算法
    |
    10月前
    |
    监控 网络协议 网络性能优化
    不再困惑!一文搞懂TCP与UDP的所有区别
    本文介绍网络基础中TCP与UDP的区别及其应用场景。TCP是面向连接、可靠传输的协议,适用于HTTP、FTP等需要保证数据完整性的场景;UDP是无连接、不可靠但速度快的协议,适合DNS、RIP等对实时性要求高的应用。文章通过对比两者在连接方式、可靠性、速度、流量控制和数据包大小等方面的差异,帮助读者理解其各自特点与适用场景。