TCP(下):三次握手四次挥手 动态控制

欢迎浏览高耳机的博客

希望我们彼此都有更好的收获

感谢三连支持!  

 TCP(上):成熟可靠的传输层协议-CSDN博客

        🥝在上篇博客中,我们针对TCP的特性,报文结构,连接过程以及相对于其他协议的区别进行了探讨,提供了初步的理解和概览。本篇中,我们将重点展开包括TCP的三次握手和四次挥手过程、滑动窗口、拥塞控制、捎带应答、延迟应答以及粘包等问题,这些都是TCP协议的关键组成部分。 

目录

连接管理 

 三次握手

四次挥手

滑动窗口 

流量控制

拥塞控制

延迟应答&捎带应答

粘包问题 

异常处理 

TCP小结


连接管理 

 🥥三次握手,四次挥手 是TCP中一个形象且重要的建立连接的机制 也是最常考的机制。

 所谓的 建立连接 ,就是通信双方各自保存对方的信息。

 三次握手

        SYN是"Synchronize"的缩写,在网络中意为“同步”。在三次握手过程中,SYN标志位用来同步连接双方的序列号,确保数据传输的顺序性和可靠性。通过交换SYN标志位的数据包,TCP连接的两端可以确认彼此都准备好进行数据传输,并且可以正确地识别和排序收到的数据包。

        ACK是"Acknowledgment"的缩写,在网络中意为“确认”。ACK标志位用于确认收到的数据包。当一个TCP段被成功接收并且没有错误时,接收方会发送一个带有ACK标志位的数据包给发送方,以告知发送方该数据包已经被成功接收。

🍇明明是"三次握手",可为什么有四个连接步骤??

将第二第三次连接步骤合并,便是三次握手的完整形态: 

        🍈如上图所示。而之所以将其合并,主要目的是提高建立连接的效率和减少延迟,服务器端可以在确认客户端的SYN请求的同时,发送自己的SYN请求,这样双方就可以在一次数据包交换中完成序列号的同步和确认,提高了建立连接的效率。同时也有节省带宽的考虑。这种设计使得TCP能够在保证可靠性的同时,提高网络通信的性能。这里运用了捎带应答的机制,下面会介绍到。

四次挥手

 

        FIN是"Finish"的缩写,FIN标志位用于终止一个已经建立的连接。FIN标志位的发送和接收标志着连接的结束阶段

  1. 第一次挥手(客户端)

    客户端决定关闭连接,并向服务器发送一个FIN标志位的数据包。这个FIN包不包含任何数据,它的作用是告诉服务器:“我这边没有数据要发送了,你可以关闭连接了。”
  2. 第二次挥手(服务器)

    服务器接收到客户端的FIN包后,会发送一个ACK标志位的数据包作为响应,确认已经收到客户端的FIN请求。这个ACK包告诉客户端:“我收到了你的关闭请求。”
  3. 第三次挥手(服务器)

    如果服务器还有未发送完的数据,它会先发送完这些数据。一旦所有数据都发送完毕,服务器也会发送一个FIN标志位的数据包给客户端,告诉客户端:“我这边也没有数据要发送了,可以关闭连接了。”
  4. 第四次挥手(客户端)

    客户端接收到服务器的FIN包后,会发送一个ACK标志位的数据包作为响应,确认已经收到服务器的FIN请求。这个ACK包告诉服务器:“我收到了你的关闭请求,现在可以关闭连接了。”

        🍉TCP四次挥手的过程中,不进行合并的原因与三次握手的情况有所不同,主要基于以下几个方面:

  1. 连接终止的单向性

    • 三次握手是建立双向通信的过程,双方都需要准备好发送和接收数据,因此需要同步序列号。
    • 四次挥手是终止连接的过程,通常是由一方(通常是客户端)发起,另一方(通常是服务器)响应。连接的终止可以是单向的,意味着一方可能还有数据要发送,而另一方可能已经没有数据要发送了。
  2. 确保数据传输完成

    • 在TCP连接中,当一方想要关闭连接时,它需要确保所有已经发送的数据都被对方接收。这通常涉及到等待数据传输的确认。
    • 四次挥手中的FIN标志位用来告知对方“我这边没有数据要发送了”,但这并不意味着所有的数据都已经被对方接收。因此,需要等待对方确认收到FIN,并且等待所有未确认的数据包被确认接收。
  3. 避免混淆状态

    • 如果在挥手过程中合并FIN和ACK,可能会导致状态混淆。例如,如果一个FIN+ACK包被发送,接收方可能会不清楚这是一个新的连接请求还是一个连接终止请求。
  4. 确保可靠性

    • 在TCP中,确保数据的可靠传输是非常重要的。在四次挥手中,每个FIN都需要一个对应的ACK来确认,这样可以确保双方都知道连接即将关闭,并且所有数据都已经被接收和处理。

        综上所述,四次挥手不进行合并是为了确保数据的可靠传输,避免状态混淆,以及确保资源的正确释放。这个过程虽然看起来效率较低,但它确保了TCP连接的可靠性和稳定性。

🍊TCP三次握手四次挥手的完整过程:

 🍋三次握手四次挥手建立连接的意义:
1.投石问路,抛砖引玉,确认当前通信路径的通畅

2.协商参数,通信双方共同确认一些通信中的必备参数数值

!!!注意!!!

TCP可靠性的保证不是三次握手四次挥手,而是确认应答和超时重传~

滑动窗口 

        🍍在上篇以及连接管理中,都涉及到了确认应答策略,对每一个发送的数据段,都要回复一个ACK确认应答。收到ACK后再发送下一个数据段。这样做有一个比较大的缺点,就是性能较差。尤其是数据往返的时间较长的时候。

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

        窗口大小指的是无需等待确认应答而可以继续发送数据的最大值。上图的窗口大小就是4000个字节(四个段)。

        发送前四个段的时候,不需要等待任何ACK,直接发送;收到第一个ACK后,滑动窗口向后移动,继续发送第五个段的数据,依此类推;操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉;窗口越大,则网络的吞吐率就越高。

        🍎如果在滑动窗口中出现丢包:若ACK丢失,则可以通过后续的ACK进行确认,问题不大;若数据包丢失,则ACK会一直返回丢包前的对应序列号,发送端就会重新发送这一部分数据,这种机制被称为"高速重发控制"。

流量控制

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

        因此TCP支持根据接收端的处理能力来决定发送端的发送速度,这个机制就叫做流量控制(Flow Control)。

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

        接收端如何把窗口大小告诉发送端呢?TCP首部中有一个16位窗口字段,存放了窗口大小信息。

        🍓那么,16位数字最大表示65535,那么TCP窗口最大就是65535字节么?实际上,TCP首部40字节选项中还包含了一个窗口扩大因子M,实际窗口大小是窗口字段的值左移M位。在位运算中,左移一位代表着乘以2,那么左移M位则是乘以2的M次方。

如果说滑动窗口是TCP在踩油门_那么流量控制就是TCP在踩刹车

并且,流量控制并不是TCP所独有的,数据链路层中的某些协议,也有流量控制机制

拥塞控制

        🫐虽然TCP有了滑动窗口这个利器,能够高效可靠的发送大量的数据。但是如果在刚开始阶段就发送大量的数据,仍然可能引发问题。因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵。在不清楚当前网络状态下,贸然发送大量的数据,是很有可能雪上加霜的。

        所以TCP引入慢启动机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据。

        此处引入一个概念称为拥塞窗口。发送开始的时候,定义拥塞窗口大小为1;每次收到一个ACK应答,拥塞窗口加1;每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小做比较,取较小的值作为实际发送的窗口。

        像上面这样的拥塞窗口增长速度,是指数级别的。“慢启动”只是指初始时慢,但是增长速度非常快。为了不增长的那么快,因此不能使拥塞窗口单纯的加倍。此处引入一个叫做慢启动的阈值。当拥塞窗口超过这个阈值的时候,不再按照指数方式增长,而是按照线性方式增长。当TCP开始启动的时候,慢启动阈值等于窗口最大值;在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置回1。

        🥝少量的丢包,仅仅是触发超时重传;大量的丢包,就会认为网络拥塞。当TCP通信开始后,网络吞吐量会逐渐上升;随着网络发生拥堵,吞吐量会立刻下降。这是TCP的动态控制机制。 

        拥塞控制,归根结底是TCP协议想尽可能快地把数据传输给对方,但是又要避免给网络造成太大压力的折中方案。

面多加水_水多加面!

延迟应答&捎带应答

        🍇如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能会比较小。假设接收端缓冲区为1M,一次收到了500K的数据;如果立刻应答,返回的窗口就是500K。但实际上可能处理端处理的速度很快,10ms之内就把500K数据从缓冲区消费掉了。

        在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一些,也能处理过来。如果接收端稍微等一会再应答,比如等待200ms再应答,那么这个时候返回的窗口大小就是1M。窗口越大,网络吞吐量就越大,传输效率就越高。在保证网络不拥塞的情况下尽量提高传输效率。这便是延迟应答
        

       🥥 很多情况下,在延迟应答的基础上,客户端服务器在应用层也是“一发一收”的。意味着客户端给服务器说了"How are you",服务器也会给客户端回一个"Fine, thank you"。这个时候ACK就可以搭顺风车,和服务器回应的"Fine, thank you"一起回给客户端。就比如在TCP三次握手中,第二次握手的ACK与SYN同时返回。这便是捎带应答

    

粘包问题 

我们知道TCP是面向字节流的协议。

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

        解决粘包问题的关键就是明确"两个包之间的边界"。对于定长的包,保证每次都按固定大小读取即可;对于变长的包,可以在包头的位置约定一个包总长度的字段,从而就知道了包的结束位置;还可以在包和包之间使用明确的分隔符,只要保证分隔符不和正文冲突即可。

        🍊对于UDP协议来说,是否也存在“粘包问题”?对于UDP,如果还没有上层交付数据,UDP的报文长度仍然在。同时,UDP是一对一把数据交付给应用层,就有很明确的数据边界。站在应用层的角度,使用UDP的时候,要么收到完整的UDP报文,要么不收,不会出现如上的情况。

异常处理 

        进程崩溃/终止:进程终止会释放文件描述符,仍然可以发送FIN。和正常关闭没有什么区别。

        机器重启:和进程终止的情况相同。

        机器掉电/网线断开:接收端认为连接还在,一旦接收端有写入操作,接收端发现连接已经不在了,就会进行reset。即使没有写入操作,TCP自己内置了一个保活定时器,会定期询问对方是否还在。如果对方不在,也会把连接释放。

        🍋另外,应用层的某些协议,也有一些这样的检测机制。例如HTTP长连接中,也会定期检测对方的状态。例如QQ,在QQ断线之后,也会定期尝试重新连接。

TCP小结

 TCP(上):成熟可靠的传输层协议-CSDN博客

        在本系列博客中,我们深入探讨了TCP的核心特性,包括🍍确认应答、🍋超时重传、🍎连接管理、🍑滑动窗口、🫐流量控制、🍓拥塞控制、🍇延时应答、🍊捎带应答以及🍉面向字节流和🥝异常处理。这些特性共同确保了TCP在网络通信中的可靠性和效率。通过理解这些机制,我们能够更好地把握网络通信的复杂性,并在现实中有效地利用TCP。

        TCP协议的深度和广度远不止于此,希望大家继续探索和学习,我期待在未来的探索中与您同行。如果您有任何疑问或想要进一步讨论的话题,请随时留言。


希望这篇博客能为你理解TCP及网络提供一些帮助

如有不足之处请多多指出

我是高耳机

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/917714.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET 部署到IIS,访问其它服务器的共享文件 密码设定

asp.net 修改上面的 IIS需要在 配置文件 添加如下内容 》》》web.config <system.web><!--<identity impersonate"true"/>--><identity impersonate"true" userName"您的账号" password"您的密码" /><co…

python实现十进制转换二进制,tkinter界面

目录 需求 效果 代码实现 代码解释 需求 python实现十进制转换二进制 效果 代码实现 import tkinter as tk from tkinter import messageboxdef convert_to_binary():try:# 获取输入框中的十进制数decimal_number int(entry.get())# 转换为二进制binary_number bin(de…

现代密码学|古典密码学例题讲解|AES数学基础(GF(2^8)有限域上的运算问题)| AES加密算法

文章目录 古典密码凯撒密码和移位变换仿射变换例题多表代换例题 AES数学基础&#xff08;GF&#xff08;2^8&#xff09;有限域上的运算问题&#xff09;多项式表示法 | 加法 | 乘法X乘法模x的四次方1的乘法 AES加密算法初始变换字节代换行移位列混合轮密钥加子密钥&#xff08…

ubuntu使用DeepSpeech进行语音识别(包含交叉编译)

文章目录 前言一、DeepSpeech编译二、DeepSpeech使用示例三、核心代码分析1.创建模型核心代码2.识别过程核心代码 四、交叉编译1.交叉编译2.使用 总结 前言 由于工作需要语音识别的功能&#xff0c;环境是在linux arm版上&#xff0c;所以想先在ubuntu上跑起来看一看&#xff…

阿里云引领智算集群网络架构的新一轮变革

阿里云引领智算集群网络架构的新一轮变革 云布道师 11 月 8 日~ 10 日在江苏张家港召开的 CCF ChinaNet&#xff08;即中国网络大会&#xff09;上&#xff0c;众多院士、教授和业界技术领袖齐聚一堂&#xff0c;畅谈网络未来的发展方向&#xff0c;聚焦智算集群网络的创新变…

PyQt5 加载UI界面与资源文件

步骤一: 使用 Qt Designer 创建 XXX.ui文件 步骤二: 使用 Qt Designer 创建 资源文件 步骤三: Python文件中创建相关类, 使用 uic.loadUi(mainwidget.ui, self ) 加载UI文件 import sys from PyQt5 import QtCore, QtWidgets, uic from PyQt5.QtCore import Qt f…

7.高可用集群架构Keepalived双主热备原理

一. 高可用集群架构Keepalived双主热备原理 (1)主机+备机keepalived配置(192.168.1.171) ! Configuration File for keepalivedglobal_defs {# 路由id:当前安装keepalived节点主机的标识符,全局唯一router_id keep_101 } #计算机节点(主机配置) vrrp_instance VI_1 {</

RHCE的学习(19)

对于RHCE的学习&#xff08;15-18&#xff09;重点总结 详细的操作还是要看之前的笔记&#xff08;甚至是RHCSA的笔记&#xff09; 1.什么是shell 一种命令解释器&#xff0c;既是用户交互的界面&#xff0c;也是控制系统的脚本语言 2.shell解释器的类型 &#xff08;bash--sh&…

微服务即时通讯系统的实现(客户端)----(2)

目录 1. 将protobuf引入项目当中2. 前后端交互接口定义2.1 核心PB类2.2 HTTP接口定义2.3 websocket接口定义 3. 核心数据结构和PB之间的转换4. 设计数据中心DataCenter类5. 网络通信5.1 定义NetClient类5.2 引入HTTP5.3 引入websocket 6. 小结7. 搭建测试服务器7.1 创建项目7.2…

【功耗现象】com.gorgeous.lite后台Camera 使用2小时平均电流200mA耗电量400mAh现象

现象 轻颜相机(com.gorgeous.lite)后台Camera 使用2小时平均电流200mA(BugReport提供的电流参考数据),耗电量400mAh 即耗电占比(200mA*2h)/(12.83h*52.68mA )400mAh/623mAh62% CameraOct 10 202321:03:08 - 23:03:372h16m15s859ms to 4h16m44s984msactive duration: 2h 0m 29…

蓝桥杯每日真题 - 第15天

题目&#xff1a;&#xff08;钟表&#xff09; 题目描述&#xff08;13届 C&C B组B题&#xff09; 解题思路&#xff1a; 理解钟表指针的运动&#xff1a; 秒针每分钟转一圈&#xff0c;即每秒转6度。 分针每小时转一圈&#xff0c;即每分钟转6度。 时针每12小时转一圈…

ctfshow-web入门-SSRF(web351-web360)

目录 1、web351 2、web352 3、web353 4、web354 5、web355 6、web356 7、web357 8、web358 9、web359 10、web360 1、web351 看到 curl_exec 函数&#xff0c;很典型的 SSRF 尝试使用 file 协议读文件&#xff1a; urlfile:///etc/passwd 成功读取到 /etc/passwd 同…

快速搭建Android开发环境:Docker部署docker-android并实现远程连接

目录 前言 1. 虚拟化环境检查 2. Android 模拟器部署 3. Ubuntu安装Cpolar 4. 配置公网地址 5. 远程访问 小结 6. 固定Cpolar公网地址 7. 固定地址访问 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业应届生 今天给大家聊聊快速搭建Android开发环境&#x…

2024-11-16-机器学习方法:无监督学习(1) 聚类(上)

文章目录 机器学习方法&#xff1a;无监督学习&#xff08;1&#xff09; 聚类&#xff08;上&#xff09;1. 聚类的基本概念1.1 聚类的概念1.2 聚类的功能1.3 聚类的算法 2. 相似度或距离2.1 闵可夫斯基距离2.2 相关系数2.3 夹角余弦 3 类或簇3.1 类的特征 4 类与类之间的距离…

Vue-组件三大组成组件通信

一、学习目标 1.组件的三大组成部分&#xff08;结构/样式/逻辑&#xff09; scoped解决样式冲突/data是一个函数 2.组件通信 组件通信语法 父传子 子传父 非父子通信&#xff08;扩展&#xff09; 3.综合案例&#xff1a;小黑记事本&#xff08;组件版&#xff09; 拆…

Scratch 014生日贺卡(上)

知识回顾&#xff1a; 1、“面向鼠标指针”积木块 2、“重复执行直到”积木块 本次分享制作生日贺卡引入广播模块 案列效果&#xff1a; 生日贺卡上案例效果-CSDN直播 步骤拆解&#xff1a; 1、添加背景和角色 2、编辑贺卡造型添加名字 3、流程图的组成和画法 4、…

MySQL中将一个字符串字段按层级树状展开

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 文章目录 需求1.分析2.实现3.思路刨析表结构和数据 需求 数据库中有个字段如下 如何将其转换为如下形式&#xff1a; 1.分析 1.他的层级个数是不确定的&#xff0c;也就是说有的有2层有的有5…

hive搭建

1.准备环境 三台节点主机已安装hadoopmysql数据库 2.环境 2.1修改三台节点上hadoop的core-site.xml <!-- 配置 HDFS 允许代理任何主机和组 --> <property><name>hadoop.proxyuser.hadoop.hosts</name><value>*</value> </property&…

创建vue+electron项目流程

一个vue3和electron最基本的环境搭建步骤如下&#xff1a;// 安装 vite vue3 vite-plugin-vue-setup-extend less normalize.css mitt pinia vue-router npm create vuelatest npm i vite-plugin-vue-setup-extend -D npm i less -D npm i normalize.css -S &#xff0…

Pyhon基础数据结构(列表)【蓝桥杯】

a [1,2,3,4,5] a.reverse() print("a ",a) a.reverse() print("a ",a)# 列表 列表&#xff08;list&#xff09;有由一系列按照特定顺序排序的元素组成 列表是有顺序的&#xff0c;访问任何元素需要通过“下标访问” 所谓“下标”就是指元素在列表从左…