传输层重点协议

news2025/1/25 9:16:30

1.TCP协议

TCP,即Transmission Control Protocol,传输控制协议。人如其名,要对数据的传输进行一个详细的控制。
 

TCP协议段格式

  1. 源/目的端口号:表示数据是从哪个进程来,到哪个进程去;
  2. 32位序号/32位确认号:
  3. 4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最大长度是15 * 4 = 60
  4. 6位标志位:
  • URG:紧急指针是否有效
  • ACK:确认号是否有效
  • PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
  • RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段
  • SYN:请求建立连接;我们把携带SYN标识的称为同步报文段
  • FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段
     

    5.16位窗口大小:

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

    7.16位紧急指针:标识哪部分数据是紧急数据;

    8.40字节头部选项:
 

2.TCP原理

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

确认应答机制(安全机制)


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

每一个ACK都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据;下一次你从哪里开始发。
 

超时重传机制(安全机制)


 

  • 主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达主机B;
  • 如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发;

但是,主机A未收到B发来的确认应答,也可能是因为ACK丢失了;
 

因此主机A会收到很多重复数据。那么TCP协议需要能够识别出那些包是重复的包,并且把重复的丢弃掉。这时候我们可以利用前面提到的序列号,就可以很容易做到去重的效果。
 

那么,如果超时的时间如何确定?

  • 最理想的情况下,找到一个最小的时间,保证 "确认应答一定能在这个时间内返回"。
  • 但是这个时间的长短,随着网络环境的不同,是有差异的。
  • 如果超时时间设的太长,会影响整体的重传效率;
  • 如果超时时间设的太短,有可能会频繁发送重复的包;
     

TCP为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间。

  •  Linux中(BSD Unix和Windows也是如此),超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。
  • 如果重发一次之后,仍然得不到应答,等待 2*500ms 后再进行重传。
  • 如果仍然得不到应答,等待 4*500ms 进行重传。依次类推,以指数形式递增。
  • 累计到一定的重传次数,TCP认为网络或者对端主机出现异常,强制关闭连接。
     

连接管理机制(安全机制)(TCP如何建立连接,TCP如何断开连接)

在正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接

TCP本来都已经保证可靠传输了,为啥还得三次握手,握2次,握4次行不行?

三次握手就是在投石问路,确认当前网络环境是否具备能够进行可靠传输,如果网络不通畅,后续会出现大规模丢包和重传,三次握手也是在进一步验证,通信双方发送能力和接收能力是否都正常。协商一些重要参数。

如果握俩次会出现以下情况:

很明显俩次握手不会保证通信正常! 

如果握四次会出现效率太低:

四次挥手:

当客户端触发FIN之后,服务器只要收到FIN,就会立即返回ACK(内核完成的)

当服务器的代码中运行到socket.close()操作的时候,就会触发FIN~ 

谁主动断开连接,谁进入TIME_WAIT

建立连接,一定是客户端主动发起,断开连接,可能是客户端,也可能是服务器主动发起

TIME_WAIT这个状态会脱离进程存在,存在的目的就是为了处理最后一个ACK丢包之后重传问题

传输的过程中,任意的包都是可能会丢的~

其中第一组FIN或者ACK丢了,此时A都是没有收到ACK,A就会重传FIN

其中第二组FIN或者ACK丢了,此时B都是没有收到ACK,B就会重传FIN 

因此A这边回复完最后一个ACK之后,不着急释放,先等一等

等一段时间之后,确保当前FIN不被重传了,然后才真的释放连接。

TIME_WAIT等待的时间叫做2MSL(MSL就是网络俩点之间消耗的最大时间)

此处的MSL的值也是可以配置的。

服务端状态转化:

  • [closed -> listen] 服务器端调用listen后进入listen状态,等待客户端连接;
  • [listen-> syn_rcvd] 一旦监听到连接请求(同步报文段),就将该连接放入内核等待队列中,并向客户端发送SYN确认报文。
  • [syn_rcvd -> established] 服务端一旦收到客户端的确认报文,就进入established状态,可以进行读写数据了。
  • [established -> close_wait] 当客户端主动关闭连接(调用close),服务器会收到结束
    报文段,服务器返回确认报文段并进入close_wait;
     
  • [close_wait -> last_ack] 进入close_wait后说明服务器准备关闭连接(需要处理完之前的数据);当服务器真正调用close关闭连接时,会向客户端发送fin,此时服务器进入last_ack状态,等待最后一个ack到来(这个ack是客户端确认收到了fin)
  • [last_ack-> closed] 服务器收到了对fin的ack,彻底关闭连接。

 客户端状态转化:

  • [closed-> syn_sent] 客户端调用connect,发送同步报文段;
  • [syn_sent -> established] connect调用成功,则进入established状态,开始读写数
    据;
  • [established -> fin_wait_1] 客户端主动调用close时,向服务器发送结束报文段,同时
    进入fin_wai_1t;
  • [fin_wait_1-> fin_wait_2] 客户端收到服务器对结束报文段的确认,则进入
    fin_wait_2,开始等待服务器的结束报文段;
  • [fin_wait_2-> time_wait] 客户端收到服务器发来的结束报文段,进入time_wait,并发
    出last_ack;
  • [time_wait-> closed] 客户端要等待一个2MSL(Max Segment Life,报文最大生存时
    间)的时间,才会进入closed状态。
     

CLOSE_WAIT
一般而言,对于服务器上出现大量的 CLOSE_WAIT 状态,原因就是服务器没有正确的关闭 socket,导致四次挥手没有正确完成。这是一个 BUG。只需要加上对应的 close 即可解决问题。
 

滑动窗口(效率机制)

刚才我们讨论了确认应答策略,对每一个发送的数据段,都要给一个ACK确认应答。收到ACK后再发送下一个数据段。这样做有一个比较大的缺点,就是性能较差。尤其是数据往返的时间较长的时候。



 

改进:

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

那么如果出现了丢包,如何进行重传?这里分两种情况讨论。

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

这种情况下,部分ACK丢了并不要紧,因为可以通过后续的ACK进行确认;


 

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

这个主机A连续发了很多数据,

1-1000
1001-2000                 在这个过程中,虽然B在不停的收到新的数据
2001-3000                 但是B一直在向A索要1001这个数据~~
                                  在B反复的几次ACK都是在索要1001之后,此时A就明白了1001这个数据怕是                                    丢了~~        

                                  就会触发重传机制~~
                                  此时就会把1001进行重传~~
                                 一旦把1001重传了之后,此时主机B就把缺失的这块数据给填补上了~~返回的                                    就是7001了.
                                  是否要返回2001 ??不需要的~~7001其实就涵盖了之前收到的一系列数据~~
                                  当B一直返回1001的时候,A仍然在努力的往后发数据.
                                  虽然B嘴上要的是1001,但是B的心里仍然默默的把A付出的这些数据都记住                                    了~~
                                  当1001这里填补上之后,B检查自己的接收缓冲区,就发现,7001之前的数据都                                   齐了于是返回的ACK就直接是7001了~~

  • 当某一段报文段丢失之后,发送端会一直收到 1001 这样的ACK,就像是在提醒发送端 "我想要的是 1001" 一样;
  • 如果发送端主机连续三次收到了同样一个 "1001" 这样的应答,就会将对应的数据 1001 -2000 重新发送;
  • 这个时候接收端收到了 1001 之后,再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中;

 这种机制被称为 "高速重发控制"(也叫 "快重传")。

流量控制(安全机制)
对滑动窗口进行了制约
滑动窗口窗口越大,就认为传输速率越高~~滑动窗口也不是越大就越好.
可靠性是第一要务I如果发的太快,接收方顶不住了,,额外发出去的数据大概率还是要丢包=>触发了超时重传.….
也不是越大越好,一定是合适才是最好的~~
发送方的发送速率要和接收方的处理速率相匹配.
流量控制,主要是根据接收方处理数据的能力,来制约发送方的滑动窗口大小.发送方的滑动窗口大小是变化的(不是固定)
如何衡量接收方的处理速率?处理的速率取决于应用程序,调用socket api读数据的速度~~

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

这里就用到数据结构中的阻塞队列,和生产者消费者的阻塞队列一样起到缓冲作用。

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

接收端如何把窗口大小告诉发送端呢?回忆我们的TCP首部中,有一个16位窗口字段,就是存放了窗口大小信息;那么问题来了,16位数字最大表示65535,那么TCP窗口最大就是65535字节么?
实际上,TCP首部40字节选项中还包含了一个窗口扩大因子M,实际窗口大小是 窗口字段的值左移 M位;
 

拥塞控制(安全机制)

  • A和B之间通过这一系列的设备进行转发传输~~
  • A到B之间的通信,一方面会受到B的处理能力的影响
  • 一方面也会受到中间的转发节点的处理能力的影响~~

相比于流量控制,拥塞控制是更复杂的~~

流量控制只考虑接收端一个人~~

拥塞控制考虑整个链路.这个链路上有多少个设备,这些设备都是啥情况??相当复杂的话题~~ 

由于这个中间的链路非常复杂.
拥塞控制的解决方案,是吧中间的整个链路视为一个整体~~通过“实验”的方式,找到一个合适的发送窗口大小~~
不断的尝试不同的窗口大小,在保证可靠性(不丢包)的前提下,尽可能的提高发送速度~~

拥塞控制会设置出一个"拥塞窗口”这样的指标.通过拥塞窗口来影响到滑动窗口的窗口大小~~
拥塞窗口也是动态变化的.刚开始用一个比较小的值(让发送方发的慢点)如果通信非常顺利,也没有丢包,就会逐渐放大拥塞窗口~~
加快发送的速度.同时密切监测丢包情况.如果加到一定程度了,发生丢包,意思就是网络链路已经顶不住~~立即再减小窗口大小让速度再慢下来如果不丢包了,再逐渐加码~~~反复重复上述过程,拥塞窗口就会逐渐稳定到某个合适的值上~~
这样的动态变化是非常有意义的~~网络环境非常复杂~~导致进行网络传输的时候很容易出现一些突然情况~~

拥塞控制会影响到滑动窗口

流量控制也影响滑动窗口~

虽然TCP有了滑动窗口这个大杀器,能够高效可靠的发送大量的数据。但是如果在刚开始阶段就发送大量的数据,仍然可能引发问题。
因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵。在不清楚当前网络状态下,贸然发送大量的数据,是很有可能引起雪上加霜的。
TCP引入 慢启动 机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据;

流量控制:限制滑动窗口大小(根据接收方的处理能力,接收方的接收缓冲区剩余空间大小)

拥塞控制:限制滑动窗口大小(根据发送方接收中间的传输链路的拥堵情况,来确定的)

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

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

延迟应答(效率机制)

如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能比较小。

  • 假设接收端缓冲区为1M。一次收到了500K的数据;如果立刻应答,返回的窗口就是500K;
  • 但实际上可能处理端处理的速度很快,10ms之内就把500K数据从缓冲区消费掉了;
  • 在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一些,也能处理过来;
  • 如果接收端稍微等一会再应答,比如等待200ms再应答,那么这个时候返回的窗口大小就是1M;

一定要记得,窗口越大,网络吞吐量就越大,传输效率就越高。我们的目标是在保证网络不拥塞的情况下尽量提高传输效率;
那么所有的包都可以延迟应答么?肯定也不是;

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

 具体的数量和超时时间,依操作系统不同也有差异;一般N取2,超时时间取200ms;

捎带应答(效率机制)


 

TCP四次挥手,有没有可能是三次呢?

有可能,因为捎带应答!

粘包问题(TCP机制延伸出来的问题)

所谓的粘包问题,指的是,当有多个TCP数据包到达的时候,如果不显式的约定包和包之间的边界,就很容易对数据产生混淆


任何的面向字节流传输机制,都会涉及到这个粘包问题。

(读写文件) 

粘包,粘的是应用层数据报,只要能够区分清楚,应用层数据报和报之间的边界,就可以区分了

靠的就是应用层协议的设定!

如果我们是使用纯TCP写客户端服务器程序,并且自己从零开始设计应用层协议,这个时候就必须特别注意粘包问题 .

重新审视一下Http(应用层协议)

Http是否存在粘包问题?Http是如何解决的粘包问题

处理粘包问题的俩种方案:

  • 1.通过分隔符
  • 2.通过长度指定 

 现成的库和框架,已经帮我们把粘包问题都处理好了~~大多数情况下,咱们也不太会遇到这个问题~~但是如果我们是需要自己动手开发一个网络相关的库/框架,大家一定要注意到这里粘包问题的效果

异常机制

建立好连接的双方,在通信的过程中,遇到了一些突发状况,如何处理?

1.进程终止

A B 其中某个进程突然终止(崩溃了,或者被强制杀死)

如果直接杀死进程,看起来是触不及防,但实际上操作系统是早有准备~~
操作系统会释放这个进程的相关资源. (TCP这里依赖了一个socket文件,操作系统就会自动的关闭这个socket文件)这个自动关闭的过程基本类似于socket.close()【触发四次挥手】

2.机器重启

按照操作系统的既定流程重启~~

点击系统的关机/重启按钮

就会由操作系统,先把当前所有的应用程序,先强制杀死~~

—杀进程,就和上面的1是一样的了!!就会释放socket 文件,同时触发FIN

3.机器掉电/网线断开

 

UDP和TCP对比

TCP:可靠性

UDP: 效率更高(分布式系统中,同一个机房内部的多个机器之间的通信,一个机房里网络结构比较简单,带宽也比较充裕,这个时候丢包的概率是不大的)

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

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

相关文章

第三章-OpenCV基础-6-滤波处理

前置内容 在尽量保留图片原有信息的情况下,过滤掉图像内部的噪声的过程成为对图像的平滑处理(又称滤波处理),所得到的图像成为平滑图像(把图像中的噪点过滤掉,生成一个相对平滑的图像)。 举个栗子: 一个图像有个噪点,加载发现有个点的像素值和周边像素值差异太大格格不入,使用…

[C++]多态

🥁作者: 华丞臧 📕​​​​专栏:【C】 各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞收藏关注)。如果有错误的地方,欢迎在评论区指出。 推荐一款刷题网站 👉LeetCode 文章目录一、多态…

【Opencv项目实战】背景替换:帮你的证件照换个背景色

文章目录方法一、基于removebg的背景替换1.1、removebg介绍1.2、环境配置1.3、算法详解1.4、实战:单张图片背景替换1.5、实战:多张图片背景替换1.6、实战:UI自选择图片进行背景替换方法二、基于backgroundremover的背景替换2.1、backgroundre…

创建对象的方式和对属性的操作

javaScript支持多种编程范式,包括函数式编程和面向对象编程,javaScript的对象被设计成一组属性的无序集合,由key和value组成。 创建对象的两种方式 早期使用创建对象方式最多的是使用Object类,使用new关键字来创建一个对象&…

应用篇|网络安全知识培训考试,答题小程序操作指引

网络安全知识培训考试,答题小程序操作指引关于全民防诈反诈宣传或者网络安全知识学习,如何进行组织一场微信线上答题考试?可以在小程序“护网专题信息安全知识竞答”,先创建一个学习单位/小组,再邀请成员加入单位/小组…

如何构造个人 AI 策略:从 AI 绘画的演进与 ChatGPT 现状出发?

持续关注 AI 相关探索:https://github.com/phodal/ai-researchPS:就本文的结论而言,我相信你已经或多或少的有所体会了。也因此,本文更多的是展现一个思考的过程,而不是一个纯粹的结论。AIGC 是什么?它是指…

pyenv安装python虚拟环境

文章目录pyenv介绍准备工作安装pyenv设置虚拟环境pyenv介绍 pyenv是一个forked自ruby社区的简单、低调、遵循UNIX哲学的Python环境管理工具, 它可以轻松切换全局解释器版本, 同时结合vitualenv插件可以方便的管理对应的包源。 为什么我们需要pyenv呢 Python解释器版本混乱, 2…

怎么关闭win10自动更新?我们可以这么做!

Win10自动更新可以使系统保持最新状态,但也可能导致一些问题,例如占用大量网络流量,导致系统速度减慢等。如果你希望关闭win10自动更新,不要电脑自动更新,我们可以跟着这篇文章这么做! 操作环境&#xff1a…

测试行业干了5年,从只会点点点到了现在的测试开发,总算是证明了自己

测试不止是点点点 我感觉我是一个比较有发言权的人吧,我在测试行业摸爬滚打5年,以前经常听到开发对我说,天天的点点点有意思没? 和IT圈外的同学、朋友聊起自己的工作,往往一说自己是测试,无形中也会被大家…

Jmeter 连接 JDBC 报错Communications link failure解决办法(云服务器搭建了LNMP环境必看)

换jar包、加?useSSLfalse,3306加防火墙,都不能解决我的问题。最终我发现是我的LNMP环境导致 错误提示 Response message:java.sql.SQLException: Cannot create PoolableConnectionFactory (Communications link failureThe last packet sent successf…

【跨尺度学习:迭代残差:超分:泛锐化】

Pansharpening via Super-Resolution Iterative Residual Network With a Cross-Scale Learning Strategy (基于跨尺度学习策略的超分辨率迭代残差网络泛锐化) 全色锐化是利用高空间分辨率全色(HR PAN)图像恢复低空间分辨率多光…

Vue-Router 路由管理器

文章目录知识点前端路由的概念及作用Vue-Router 的安装Vue-Router 的基本使用知识点 前端路由的概念及作用Vue-Router 的安装Vue-Router 的基本使用 前端路由的概念及作用 需要大家注意的是,这里的路由可不是指我们日常生活中的路由器 😂 ,…

Allegro如何打开或者关闭DFA规则设置操作指导

Allegro如何打开或者关闭DFA规则设置操作指导 在用Allegro做PCB布局的时候,器件与器件之间的DFA规则可以避免器件出现装配问题。如下图 当DFA规则设置好之后,如何打开或者关闭规则,具体操作如下 点击Setup点击Constraints

华为OD机试题,用 Java 解【相同数字的积木游戏 1】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…

2023年“网络安全”赛项浙江省金华市选拔赛 任务书

2023年“网络安全”赛项浙江省金华市选拔赛 任务书 任务书 一、竞赛时间 共计3小时。 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段单兵模式系统渗透测试 任务一 Windows操作系统渗透测试 任务二 Linux操作系统渗透测试 任务三 网页渗透 任务四 Linux系统…

硬件工程师——门控开关的设计

假设自己是一个工程师,那么我们怎么介绍自己呢? 我们首先需要可以自己独立设计项目,需要每一个工程师在开始阶段可以独立做项目,从而提高薪水 那么我们怎么提高做项目的能力呢? 通过项目来积累经验,在短…

百亿数据,毫秒级返回查询优化

近年来公司业务迅猛发展,数据量爆炸式增长,随之而来的的是海量数据查询等带来的挑战,我们需要数据量在十亿,甚至百亿级别的规模时依然能以秒级甚至毫秒级的速度返回,这样的话显然离不开搜索引擎的帮助,在搜…

OpenHarmony的未来和如何做好一个开源社区

今天要分享的文章,可能更多只是作为一种观点。主要包括2个内容。OpenHarmony的未来和如何做好一个开源社区,好的,接下来开始今天的内容。 你对OpenHarmony的未来如何看待? OpenHarmony的未来看起来非常光明,因为它具…

把 ChatGPT 加入 Flutter 开发,会有怎样的体验?

前言 ChatGPT 最近一直都处于技术圈的讨论焦点。它除了可作为普通用户的日常 AI 助手,还可以帮助开发者加速开发进度。声网社区的一位开发者"小猿"就基于 ChatGPT 做了一场实验。仅 40 分钟就实现了一个互动直播 Demo。他是怎么做的呢?他将整个…

如何管理好仓库/库房?

仓库管理是企业管理中不可缺少的一部分,事关企业能否正常运行的关键之一,古人有云:“三军未动粮草先行”,一个企业仓库管理做不好,他的生产管理肯定也是做不好的,不是说生产管理人员的管理能力不具备&#…