吐血整理的TCP协议相关原理

news2024/11/17 7:54:50

文章目录

  • 一、 TCP报文的结构
  • 二、TCP建立连接-三次握手
    • 2.1 三次握手建立连接的过程
    • 2.2 三次握手的思考
    • 2.3 针对连接过程的DDOS攻击-SYN flood
  • 三、 TCP断开链接-四次挥手
    • 3.1 客户端主动断开链接的过程
    • 3.2 四次挥手的思考
  • 四、 TCP状态机
  • 六、 TCP的流量控制-滑动窗口协议
  • 七、 TCP拥塞控制-拥塞窗口cwnd(congestion window)
  • 八、 TCP的性能分析和优化

     TCP 传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

吐血整理的TCP相关的知识,包括TCP的连接建立、连接断开,三次握手、四次挥手、还有TCP的包确认、延迟确认、慢启动、滑动窗口、拥塞控制、累计应答等和TCP相关的概念做了一个梳理。有些地方没有深入去写,因为我们毕竟不用自己去实现TCP协议,但是理解TCP的各个机制和算法可以很好的学习到设计一个靠谱的协议需要考虑到的东西是多么细致复杂。 老铁们一次看不完可以加个收藏先。

一、 TCP报文的结构

在这里插入图片描述

字段作用
源端口和目标端口用来标识这个包从哪个程序发出的,和发到目标机器上由哪个程序接收。
序号 seq用来保证数据包的有序性,不然无法确定发出去的数据包的先后也没办法重新组装。
确认序号 ack用来确认收到的包的序号,可以以此告诉对方包已收到,否则就需要重发。
状态位SYN 发起连接、ACK回复、RST重新连接、FIN端开连接、UGR紧急标志位,标识紧急指针有效。、PSH标志位让接收方收到该数据后立即从TCP缓冲区中拿走该数据。
紧急指针配和URG标志位才有效,指向数据中某个字节的结尾。此时数据从开始只紧急指针位置,为紧急数据。

二、TCP建立连接-三次握手

TCP连接
一个TCP连接通过四个值来识别的,也叫TCP四元组,这四个值一起唯一定义了一条连接。< 源 IP 地址、 源端口号、 目的 IP 地址、 目的端口号 >。TCP连接的建立,可以简化为 请求->应答->应答之应答 虽然只有3个回合但里面有很多细节。

2.1 三次握手建立连接的过程

  1. 初始时,客户端和服务端连接未建立都是处于Close状态,服务端主动监听某个端口,处于LISTEN监听状态,然后客户端主动打开并发起TCP连接。
  2. 第一次握手:客户端发送连接请求,标志位SYN=1 并且附带连接的起始序号seq=x,seq是从一个32位计数器中获取,这个计数器4微秒+1。问:这里序号为啥不从1开始?
  3. 第二次握手:服务端收到连接请求后,回复消息 SYN=1 ACK=1 seq=y ack=x+1 这里的seq=y是服务端的连接序号。
  4. 第三次握手:客户端发送 ACK=1 seq=x+1 ack=y+1
  5. 握手完成后客户端和服务端就可以开始互相通信了。

image.png

2.2 三次握手的思考

| 问题 | 思考 |
| --- | --- |
| **为什么要有三次握手?** | > 网络中数据到达的顺序不一定和收到的顺序一致1、防止建立没必要的连接
如果只有两次握手就开始发送数据了,发送完成后连接断开了。结果服务端收到了在网络中晃悠半天的第一次握手的数据包,那么服务器回复第二次握手后就又建立了连接,这个连接时没必要的。
如果又第三次握手,客户端收到第二次握手后,客户端知道这是多余的数据包,不进行第三次握手连接就没有被建立。
2、让客户端和服务端双方明确,自己和对方收发包能力都是正常的。 |
| **为包的序号seq不从1开始** | 1、防止不是同一次连接的同序号的包干扰正常的数据传输
假如每次seq从1开始,然后有一个属于连接A数据包序号为4在网络里多走了一会儿,然后这个期间那个数据包的数据发完了连接A已经断开了,假设同样的连接又建立起来了,开始发送数据这次只有三个数据包 1、2 、3,但是上次A的序号为4的包又到了,则会被一起组装产生错误的数据。 |

2.3 针对连接过程的DDOS攻击-SYN flood

DDOS又称为分布式拒绝服务,全称是Distributed Denial of Service。DDOS本是利用合理的请求造成服务器资源过载,导致服务不可用。常见的DDOS攻击有SYN flood(SYN flood)、UDP flood、ICMP、flood等,其中SYN flood是一种最为经典的DDOS攻击。SYN flood如此猖獗是因为它利用了TCP协议设计中的缺陷,而TCP/IP协议是整个互联网的基础,牵一发而动全身,如今想要修复这样的缺陷几乎成为不可能的事情。

SYN flood攻击原理

  1. SYN flood在攻击时,首先伪造大量的源IP地址,分别向服务器端发送大量的SYN包。
  2. 服务器端返回SYN/ACK包,因为源地址是伪造的,所以伪造的IP并不会应答。
  3. 服务器端没有收到伪造IP的回应,会重试3~5次并且等待一个SYN Time(—般为30秒至2分钟),如果超时则丢弃这个连接。
  4. 攻击者大量发送这种伪造源地址的SYN请求,服务器端将会消耗非常多的资源来处理这种半连接,同时还要不断地对这些IP进行SYN+ACK重试。
  5. 最后的结果是服务器无暇理睬正常的连接请求,导致拒绝服务。

三、 TCP断开链接-四次挥手

TCP是一个全双工协议,所以任一方都可发送数据,发送断开。
数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于established(表示连接已经建立)状态,然后客户端主动关闭,服务器被动关闭。

3.1 客户端主动断开链接的过程

image.png

  1. 第一次握手:客户端发送断开连接报文 FIN=1,seq=u ,并停止发送数据。客户端进入FIN-WAIT-1 状态。TCP规定,FIN报文即使不携带数据也要消耗1个序号。
  2. 第二次握手:服务端收到连接释放报文,回复确认报文 ACK=1 ack=u+1 seq=v,服务端此时进入了 CLOSE-WAIT 关闭等待状态。此时TCP服务通知上层应用进程,客户端数据发送完毕,即将释放连接。此时服务器端如果仍有数据要发送,客户端将继续接收,这个状态持续的时间,就是等待关闭的时间。
  3. 客户端收到服务端发送的ACK后,进入FIN-WAIT-2状态,这个状态时仍然接收服务器发送的数据。等待服务器发送释放报文。
  4. 第三次握手:服务端数据发送完毕,可已断开时。发送释放连接报文, FIN=1 ACK=1 seq=w ack=u+1 这里的W是假设中间服务端又发送了一堆数据,但是为什么ack还是u+1我也没找到,是为了标识回复的哪条消息?
  5. 第四次握手:客户端收到服务器的释放连接报文后,回复确认 ACK=1 seq=u+1 ack=w+1,此时连接还没完全关闭,客户端进入了TIME-WAIT 时间等待状态,TCP连接并未关闭,必须等待 2*MSL(最长报文段寿命)后,才进入CLOSED状态
  6. 服务端收到客户端回复的确认关闭,就进入了CLOSED状态,结束了本次连接。比客户端关闭时间更早。

3.2 四次挥手的思考

在这里插入图片描述

四、 TCP状态机

1677411374668-11bd5e09-4ed3-4286-b47d-82fec91842ce.png


# 五、TCP如何实现靠谱的传输
  1. 数据包编号 : TCP为了保证顺序性,会给每个包分配一个序号,建立连接时会确定双方包序号的起始值。
  2. 包确认: 发送确认TCP对于发送的包都需要对方进行应答。不过为了提高效率并不需要对每个包分别应答,而是应答最后一个包,就可以表示这个包之前的包都已接收。这个机制称为:累计确认/累计应答
  3. 丢包重发: tcp对于丢失包进行重发,有几种处理机制 **1.超时重传 2.快速重传 3.SACK选择性确认 4.Duplicate - SACK **
    在这里插入图片描述

六、 TCP的流量控制-滑动窗口协议

顺序问题、丢包问题、流量控制都是通过滑动窗口来解决的,这其实就相当于你领导和你的工作备忘录,布置过的工作要有编号,干完了有反馈,活不能派太多,也不能太少;

使用滑动窗口的TCP缓存结构

  1. TCP为了记录所有发送的包和接收的包,发送端和接收端,都有自己的缓存。
  2. 发送端的缓存里按照包的id顺序排列,根据处理情况分为四个部分:1发送并已确认接受 2已发送但未确认接收 3没有发送但是已经准备发送的 4没有发送,并且暂时不会发送的。
  3. 接收端缓存分为:1接收并返回了确认 ;2没收到但是还能接收处理的 ;3没接收收到也处理不了的。
  4. 接收端会给发送端一个窗口大小,**Advertised window(公告窗口) **这个值会根据网络情况进行调整。这个就是滑动窗口,动态的调整这个值,就能起到流量控制的功能。这个值对于发送端来说,就等于发送了未确认的部分+未发送但可发送的部分。


    发送端的缓存结构
    image.png


    接收端的缓存结构
    在这里插入图片描述
  5. MaxRcvBuffer 表示这个TCP连接最大可用于接收的缓存,超出这个部分的接收到了也无法处理。
  6. LastByteRead 在接收已确认部分中,被应用层读取的与未被读取的分界线,一般被读取出去了就不在缓存了。
  7. NextByteExpected 等待接收数据的部分的起始值
  8. Advertised window 窗口的大小,就相当于最大缓存大小MaxRcvBuffer 减去 接收且确认中未被读出缓存的部分。AdvertisedWindow=MaxRcvBuffer-((NextByteExpected-1)-LastByteRead)

利用窗口进行流量控制

tcp接收端在对收到的数据包返回ACK确认时,会同时返回窗口的大小,如果接收端处理不过来,接收端就能动态的调整窗口大小来进行流量控制。

窗口大小不变的情况

  1. 发送端收到一个确认,那么窗口就会对应的右移一个包长度,这时未发送但可发送部分长度+1
  2. 如果将未发送可发送部分全都发送出去了,那么由于窗口限制就会暂停发送,直到收到新的确认包。

接收方处理能力弱,修改窗口让发送端发慢点

  1. 假设一种极端情况,接收数据的应用一直不读取tcp接收端缓存的数据,那么每次返回一个确认包,窗口的大小就会-1
  2. 直到最后lastByteRead会变到MaxRcvBuffer同一个位置,缓存被已接受确认但未被读取的数据包占满。这时候窗口的大小就是0了
  3. 这个过程中随着窗口逐渐减小,发送端能发送的数据也会一直减小,到最后窗口为0就停止发送。
  4. 窗口大小为0之后,发送端会定时发送探测数据包,看看窗口恢复了没。这时候还有一个要注意的,就是接收端不会说一空出1个数据包就立即修改窗口大小,会直到窗口恢复到一定的大小,才会更新窗口。不然就会出现低能窗口综合征。



七、 TCP拥塞控制-拥塞窗口cwnd(congestion window)

滑动窗口主要是解决接收方处理能力不足主的问题。拥塞控制也是通过窗口的大小来控制的,TCP的cwnd 就是拥塞窗口。

为什么要拥塞控制

  1. TCP拥塞控制的目的,就是在最小的消耗(不丢包,不重传)的情况下,最大程度的利用网络的带宽
  2. 如果没有拥塞控制,那么发送的太快了就会大量丢包重发,重发包又会继续堵塞网络通道
  3. 如果发送的太慢了,那么传输的速度又太低了,传输的时延无法保证。
  4. TCP的发送速度,其实取决于两个窗口值中最小的一个值。rwnd就是接收方滑动窗口(receiver window) 公式:lastByteSent - LastByteAcked <= min {cwnd,rwnd}

cwnd的工作流程

cwnd和ssthresh的单位都是字节,ssthresh=cwndmss,所以比较时可以假设是包个数。
下面说的达到ssthresh意义是cwnd
mss大于或等于ssthresh
MSS含义是Maximum Segment Size 最大报文长度,和链路层的MTU不同,MTU能包住MSS

  1. tcp连接刚刚建立时,网络的情况对于TCP连接来说是完全不可知的,只有开始传输数据了才能知道网络的速度,这时候cwnd 被设置为1 ,这一机制被称为TCP的慢启动。cwnd的大小则表示发送端一次能发送多少个数据包。
  2. 慢开始算法 指数增长阶段(cwnd<ssthresh):如果传输很顺畅(没超时没重发,能正常收到ACK),那么cwnd就会开始以指数级开始增长,收到第一个ACK cwnd+1; 收到第二个ACK cwnd+2;cwnd的变化序列,1、2、4、8、16 . . .
  3. 指数增长阶段会在什么时候结束呢?会在cwndmss达到了ssthresh的值 65535字节,cwnd改为线性增长阶段。或者是在出现了超时重传的情况时(网络阻塞)开始转为线性增长。默认的ssthresh设置的如此之大,其实就是为了能最大的速度经历一次丢包,丢包后ssthresh的值会被重新设定为cwnd/2mss,而cwnd也会重新被设置为1 重新开始慢启动
  4. 拥塞避免算法 线性增长阶段(cwnd>ssthresh):cwnd达到了ssthresh的值后,假如此时的cwnd是6 那么一次发送6个数据包,每次收到1个ACK cwnd就增加1/6 ,这时cwnd的增长就是线性增长阶段。
  5. 出现拥塞 超时重传或者快速重传, 出现丢包导致的超时重传,ssthresh的值会被重新设定为cwnd/2*mss ,然后cwnd重新设置为1 重新开始慢启动。快速重传的丢包TCP则不会认为是网络出现严重拥堵因为还能正常收到ACK,所以cwnd 减半为 cwnd/2 ,sshthresh = cwnd,然后每次收到确认之后cwnd+1 这是快恢复算法。

image.png
TCP BBR 拥塞算法
通过上面的cwnd拥塞窗口,TCP实现了基础的拥塞控制,但是有两个问题并未得到妥善的解决

  1. 丢包不一定是通道被完全占满,而是有一定的随机性,一出现丢包就主动降速可能不合适
  2. 一旦大量丢包,则说明网络中传输设备的缓存都已经被占满了,这个时候才开始降速已经有点晚了,这种处理方式会使得网络的延时增大并且变得不稳定。

最理想的场景tcp传输过程中,应该尽可能的占满通道,而不填满通道的缓存,这样延时和速率都是一个比较均衡的状态。而**TCP的BBR拥塞算法,**就是企图找到一个平衡点的功能。

八、 TCP的性能分析和优化

应用层建立在传输层之上,所以HTTP这种应用层协议的速度受到传输层速度影响很大。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

openpnp - 顶部相机高级矫正的细节

文章目录openpnp - 顶部相机高级矫正的细节概述ENDopenpnp - 顶部相机高级矫正的细节 概述 设备到手的时候, 只有一个主校准点, 是一块只带一个mark点的小PCB拧在设备正面前部中间的凸台上. 配置openpnp时, 需要指定次校准点. 开始自己做了一块长条形PCB, 上面有mark点, 拧在…

【C++知识点】重载

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;C/C知识点 &#x1f4e3;专栏定位&#xff1a;整理一下 C 相关的知识点&#xff0c;供大家学习参考~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;…

阿赵的MaxScript学习笔记分享十二《获取和导出各种数据》

大家好&#xff0c;我是阿赵&#xff0c;周日的早上继续分享MaxScript学习笔记&#xff0c;这是第十二篇&#xff0c;获取和导出各种数据 1、导出数据的目的 使用3DsMax建立3D模型后&#xff0c;很多时候需要输出模型到别的引擎去使用&#xff0c;常用的格式有Obj、FBX、SLT等…

geoserver之BlobStores使用

概述 geoserver是常用的地图服务器之一&#xff0c;除了基本的能力之外&#xff0c;也提供了很多的插件方便大家使用。在本文&#xff0c;讲述一下如何在geoserver中使用BlobStores和gwc-sqlite-plugin插件实现地图的切片和部署。 BlobStores简介 在geoserver中&#xff0c;…

Linux安装Nginx和Nginx基础配置

下载Nginx 方式一&#xff1a;通过官网下载后上传 通过官网下载安装包。下载地址https://nginx.org/en/download.html 这里选择稳定版的进行下载。 这里使用FinalShell终端工具操作&#xff0c;使用其他工具操作亦可。FinalShell工具下载地址&#xff1a;http://www.hostbuf…

带加权的贝叶斯自举法 Weighted Bayesian Bootstrap

在去年的文章中我们介绍过Bayesian Bootstrap&#xff0c;今天我们来说说Weighted Bayesian Bootstrap Bayesian bootstrap 贝叶斯自举法&#xff08;Bayesian bootstrap&#xff09;是一种统计学方法&#xff0c;用于在缺乏先验知识的情况下对一个参数的分布进行估计。这种方…

【Node.js】HTTP协议、HTTP的请求报文和响应报文

HTTP协议、HTTP的请求报文和响应报文HTTP协议HTTP主要特点HTTP的请求报文和响应报文请求报文请求行请求消息头空行请求体响应报文响应状态行响应消息头空行响应体总结HTTP协议 HTTP 全称为超文本传输协议&#xff0c;是用于从WWW服务器传输超文本到本地浏览器的传送协议&#…

硬件基础专题-01电阻篇

目录 课程链接 学习目的 电阻 电阻理论讲解 电阻定义​ 欧姆定律​ 电阻单位换算 电阻选型考虑 安装方式 常见电阻值 各种贴片电阻的读取方式 确定电阻值的方法 电阻数据手册 电阻测量 电阻的产品应用​ 零欧姆电阻 热敏电阻 光敏电阻 课程链接 视频专辑 - 硬件…

linux入门---权限

目录标题什么是权限人的分类为什么会有所属组查看文件属性文件的分类如何查看权限文件不同权限的表现rwx权限修改八进制权限修改umask有关内容文件中人的修改目录不同权限的表现rwx什么是权限 首先来看一个例子&#xff1a;比如说我没有爱奇艺的vip&#xff0c;那么我也就没有…

训练CV模型常用的方法与技巧

最近参加一个CV比赛&#xff0c;看到有参赛者分享了自己训练图像识别模型时常用到的小技巧&#xff0c;故对其进行记录、整理&#xff0c;方便未来继续学习。整理了很多&#xff0c;它们不一定每次有用&#xff0c;但请记在心中&#xff0c;说不定未来某个任务它们就发挥了作用…

JavaScript-扫盲

文章目录1. 前言2. 第一个 JavaScript 程序3. javaScript 的基础语法3.1 变量3.2 数据类型3.3 运算符3.4 条件语句3.5 数组3.6 函数3.7 作用域3.8 对象4. WebAPI4.1 DOM 基本概念4.2 常用 DOM API4.3 事件4.4 操作元素4.5 网页版猜数字游戏4.6 留言版1. 前言 提问 java 和 java…

数字图像学笔记 —— 17. 图像退化与复原(自适应滤波之「最小二乘方滤波」)

文章目录维纳滤波的缺点约束最小二乘方滤波给一个实际例子吧维纳滤波的缺点 维纳滤波&#xff08;Wiener Filter&#xff09;&#xff0c;虽然是一种非常强大的退化图像还原算法&#xff0c;但是从实验过程我们也发现它存在着致命的缺陷&#xff0c;那就是要求输入退化系统的 …

医疗器械之模糊算法(嵌入式部分)

模糊控制 所谓模糊控制&#xff0c;就是对难以用已有规律描述的复杂系统&#xff0c;采用自然语言&#xff08;如大&#xff0c;中&#xff0c;小&#xff09;加以描述&#xff0c;借助定性的&#xff0c;不精确的以及模糊的条件语句来表达&#xff0c;模糊控制是一种基于语言的…

Java虚拟机JVM-运行时数据区域说明

及时编译器 HotSpot虚拟机中含有两个即时编译器&#xff0c;分别是编译耗时短但输出代码优化程度较低的客户端编译器&#xff08;简称为C1&#xff09;以及编译耗时长但输出代码优化质量也更高的服务端编译器&#xff08;简称为C2&#xff09;&#xff0c;通常它们会在分层编译…

【Linux】手把手教你在CentOS上使用docker 安装MySQL8.0

文章目录前言一. docker的安装1.1 从阿里下载repo镜像1.2 安装docker1.3 启动docker并查看版本二. 使用docker安装MySQL8.02.1 拉取MySQL镜像2.2 创建容器2.3 操作MySQL容器2.4 远程登录测试总结前言 大家好&#xff0c;又见面了&#xff0c;我是沐风晓月&#xff0c;本文主要…

docker系列1:docker安装

传送门 docker官网地址&#xff1a; Docker: Accelerated, Containerized Application Development 安装地址&#xff1a;Install Docker Engine docker hub地址 docker hub&#xff1a;Docker 安装步骤 前置条件 由于安装docker&#xff0c;需要根据操作系统版本选择…

设计模式(只谈理解,没有代码)

1.什么是设计模式设计模式&#xff0c;是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。2.为什么要学习设计模式看懂源代码&#xff1a;如果你不懂设计模式去看Jd…

【react全家桶】生命周期

文章目录04 【生命周期】1.简介2.初始化阶段2.1 constructor2.2 componentWillMount&#xff08;即将废弃&#xff09;2.3 static getDerivedStateFromProps&#xff08;新钩子&#xff09;2.4 render2.5 componentDidMount2.6 初始化阶段总结3.更新阶段3.1 componentWillRecei…

2023最新版本RabbitMQ的持久化和简单使用

上节讲了 RabbitMQ下载安装教程 &#xff0c; 本节主要介绍RabbitMQ的持久化和简单使用。 一、RabbitMQ消息持久化 当处理一个比较耗时得任务的时候&#xff0c;也许想知道消费者&#xff08;consumers&#xff09;是否运行到一半就挂掉。在当前的代码中&#xff0c;当RabbitM…

如何在本地跑FuzzBench的实验

概述 FuzzBench是谷歌做的一个评估模糊测试的benchmark&#xff0c;主要目的是为了评测覆盖率导向模糊测试工具能达到多少覆盖率&#xff0c;能够发现多少漏洞。本文主要介绍如何在本地运行fuzzbench的实验。当然也可以用谷歌的云服务来跑&#xff0c;具体教程在这&#xff1a…