首页 > 其他分享 >网络世界的“交通规则”——TCP/IP(一)

网络世界的“交通规则”——TCP/IP(一)

时间:2025-01-05 19:32:10浏览次数:11  
标签:ACK IP 报文 TCP 交通规则 发送 数据包 应答

一、非可靠传输的协议——UDP

1.1 UDP的报文格式

(1)UDP长度:表示整个UDP数据包的长度(报头+载荷);

(2)校验和:用于验证UDP数据包在传输过程中有没发生比特翻转(由于各种原因导致的比特位变化,如0变为1,接收方在收到数据包后会重新进行校验和的计算,如果与UDP数据包中的校验和不同,就会丢弃这个数据包),前面所学的HTTPS中证书的数字签名本质上就是一段被加密的校验和。


1.2 UDP的特点

(1)无连接:知道对方的IP端口号就能进行传输,不用建立连接

(2)不可靠:没有确认重传机制,如果发送的数据报没有到达对方,UDP不会做出任何处理,对方也不知道发送方向自己发送了数据

(3)面向数据报:不能灵活控制数据读写的次数和数量

!!!但是除此之外,UDP在大部分情况下为TCP所取代的原因还有:由于UDP报头中UDP长度的大小仅有16位,只能够表示64kb的大小,对于现在来说是不够的(可能随便发送一个图片就要几个mb ),如果非要用UDP来传输的话,就需要拆分和组合数据报,非常麻烦


 二、可靠传输的协议——TCP

2.1 TCP的报文格式

目前只讨论部分字段,其余字段将在后面了解到:

(1)16位源端口号/16位目的端口号:传输层的核心内容

(2)4位首部长度:4位,表示整个数据包的大小,使用4字节为单位(如4个比特位最多表示15,15x4=60字节)

(3)保留(6位):为未来可能的协议扩展或新功能预留的,目前保留位通常被设为0

(4)6位标志位:包含URG等6个字段,是TCP最核心的6个标志位


2.2 TCP的核心机制

2.2.1 保证传输可靠性的机制

这里所说的可靠性并不是说A给B发送一组数据,B一定能收到,而是尽可能的让B收到,就算B收不到,A也能知道

2.2.1.1 核心机制一——确认应答

如A给B发送一组数据,B接收到以后,会向A发送一个应答报文。

什么是应答报文?

答:应答报文也是一个TCP数据报,但是它的载荷不携带任何信息,在发送应答报文时,只需要将6位标志位中的ACK设置为1即可。

  确认应答的过程是怎么样的?(图示)

  但是,对于上述确认应答的过程,有没有可能A给B发了不止一个数据报,而B的应答报文发错对象了呢?如图:

  为了解决这种情况,TCP引入了序号和确认序号两个字段

(1)序号主要是用在传输数据的报文中的(即载荷不为空的报文),当然在后面建立连接和关闭连接等阶段的报文也会使用。

(2)确认序号主要是用在ACK为1的应答报文或其他如(FIN + ACK)报文中的(也就是只有ACK为1的报文中的确认序号才生效)。

  序号相当于对A的数据做了一个编号,而确认序号可以表示这个ACK是对特定序号的回复

  在实际传输过程中,是如何对数据进行编码的呢?TCP采取的是对每个字节都进行编码,如

图:(下图表示每1000个字节为一个TCP数据包)

   它的确认应答机制如下图:可以看到,确认序号的内容是将收到的数据报的载荷的最后一个字节的编号+1得到的

  !!!确认序号的含义?

  表示小于确认序号的数据报都已经收到了,接下来可以从序号为确认序号的序号开始发送数据报了(如确认序号为2001,表示1~1000还有1001~2000的数据包都已经收到)

引入序号之后,接收方就可以对收到的数据进行排序,确保应用程序通过socket api读取到的数据顺序是正确的 ,那么,具体的读取过程如何?

(1)TCP会在接收方安排一个接收缓冲区

(2)从网卡中读取到的数据,会先放到接收缓冲区中,后续代码调用read方法读取数据,也是从接收缓冲区读

(3)在接收缓冲区中,收到的数据是根据序号来排序的,如果前面的数据还没到,后面的数据先到了,read就会进入阻塞,只有前面的数据到了,read才可以解除阻塞


2.2.1.2 核心机制二——超时重传

由于网络数据的传输链路复杂多样,各路由器/交换机的状态(是否繁忙)又不可知,导致数据在传输过程中会不可避免的出现丢包,为了应对可能出现的丢包,TCP引入了重传机制。

假设A给B发送了一个数据

(1)如果一定时间(即超时时间)内A还没有收到B发来的应答报文(ACK),A就会重新发送数据报给A(超时时间的阈值是动态变化的,如果这次超时了,那么阈值就会提高)

(2)如果超时次数达到一定次数,就会认为网络出现了严重故障,放弃此次传输。

这里出现的丢包状况有两种可能:对于这两种可能,A是无法分辨的,都是重发数据报


2.2.2 核心机制三——连接管理
2.2.2.1 三次握手——建立链接

(一)三次握手的过程

<1>客户端A先给服务器B发送一个SYN(同步报文),表示希望与B建立连接

<2>B收到SYN后,会发送一个ACK + SYN报文,表示已经收到A的SYN,且在B发送的SYN+ACK报文中还包含着一段序列号,用于标识B后续发送数据的起始位置(如初始序列号为5000表示B接下来发送的数据从5000开始编号)

<3>A收到B发送的ACK+SYN报文后也会给B发送一个ACK,表示已收到


(二)三次握手有什么用?

<1>确定双方的通信链路是否正常

<2>确定双方的发送能力和接收能力是否正常

<3>可以协商一些关键信息,如上面提到的序列号(表示接下来发送的数据的序号从哪里开始)


(三)三次握手过程中客户端和服务器对应的状态


2.2.2.2 四次挥手——断开连接 

(一)四次挥手的过程

<1>A向B发送一个FIN报文(终止报文),表示断开此次连接

<2>B收到 A发来的FIN后 ,向A发送ACK表示收到

<3>B再发送一个FIN报文给A(触发A关闭连接)

<4>A收到 B发来的FIN后 ,也会向B发送ACK表示收到


(二)四次挥手中双方的状态

!!!在四次挥手过程中可能会发生丢包的问题,TIME_WAIT的作用之一就是为了防止最后一次发送的ACK丢包(有一定的等待时间,防止在对方还没有收到ACK就关闭连接,且刚好ACK发生丢包的情况)


2.2.3 核心机制四——滑动窗口

 TCP是以牺牲效率来保证可靠性的,而滑动窗口通过批量发送一组数据可以在保证可靠性的基础上提高一些效率,如图:

相当于用原来的一份时间等待多组ACK

在A收到一个ACK后,不是继续等待剩下的ACK都到了才发下一条数据,而是直接发送下一条数据,如图:(同理,如果是3001的ACK先到了的话窗口就直接向后移动两个格子(因为后一个ACK可以涵盖前一个ACK的含义,如先收到3001,就表示1~3000所有的数据报都已经收到了))

当然,在滑动窗口中也可能发生丢包,分为两种情况

(一)ACK丢了

这种情况不用做任何处理,因为前面也说过后一个ACK可以涵盖前一个ACK的含义


(二)数据包丢了

  可以看到,如果前面的数据包丢包了,就算后面的数据包到了ACK中的确认序号也还是前面丢失数据包的起始序号

  如果数据发送方连续收到3个同样的确认应答,就会进行快速重传,重新发送这部分数据。

  直到主机A将1001~2000的数据包重新发送并且被接收,ACK中的确认序号才会更新。


2.2.4 核心机制五——流量控制 

   前面说到,滑动窗口可以在确保可靠性的前提下,批量发送一组TCP数据包,那是否批量发送的数据包越多越好呢?其实不是,如果批量发送的数据过多就无法确认可靠性了,因此TCP中引入了流量控制。

   TCP支持根据接收端的处理能力, 来决定发送端的发送速度. 这个机制就叫做流量控制

 

   那如何衡量接收端盖的处理能力呢?

答:在ACK中依赖一个字段——16位窗口大小,发送方会根据ACK中的窗口大小,动态的调整滑动窗口的窗口大小。

  那16位窗口大小中的数据是怎么得到的呢?

答:在new 一个Socket对象的时候,会在操作系统内核中分配一个接收缓冲区,窗口大小的值,就是接收缓冲区中剩余空间的大小。

   如果得到的窗口大小为0,怎么办?

答:


2.2.5 核心机制六——拥塞控制 

  流量控制是根据接收方的接收能力来控制的,但是两台主机进行通信过程中,两台主机可能并不是简单的连接,其中可能涉及到复杂的数据传输链路,如果数据链路过于繁忙,也会导致丢包,因此,拥塞控制就是根据数据链路的转发能力决定发送端的发送速度

 

  那么,如何衡量数据链路的转发能力?

答:通过实践来得出,如发送方先发送少量数据,如果没有出现丢包情况,就持续增大发送的数据量,如果出现丢包情况,就减少发送的数据量,动态的调整。具体的调整过程如下图:

因此,拥塞控制的工作过程可以描述为:慢启动——>指数增长——>线性增长——>出现丢包,窗口变为较小值


2.2.6 核心特性七——延时应答

  一般情况下,接收方在收到数据后会立即返回ACK,但是实际上我们可以通过延时应答来提高效率,如在前面计算窗口大小的时候,如果我们直接返回ACK也可以,但是否可能在ACK还没有到达对方的时候,接收缓冲区中的数据就又被读取了很多使剩余空间大小增大了呢?

很有可能,因此如果使用延时应答,就可以放回一个较大的窗口大小,提高了效率 。

   但是,并不是所有的包都可以延时应答,一般

<1>数量限制:一般每个几个包就应答一次

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


2.2.7 核心特性八—— 捎带应答

   捎带应答是在延时应答的基础上建立的,它可以使得携带业务数据的报文和应答报文处于同一时期发送,这样一来就可以合并这两个报文了,起到提高效率得作用。

   前面四次挥手过程中的FIN报文和ACK报文也后可能因为延时应答处于同一时机而被合并。


2.2.8 核心特性九——面向字节流

  我们要讨论的问题其实并不是面向字节流本身,而是面向字节流所带来的问题——粘包问题, 即无法区分从哪个数据包到哪个数据包是一个完整的应用层数据包。

  对于粘包问题,在TCP层面上误解,只能从应用层解决:

<1>约定包与包之间的分隔符,如以 /n 作为包的结束标记;

<2>约定包的长度,如将每个包的前4个字节用来表示数据包的长度;

  在HTTP中,对于get请求,没有body,使用空行作为结束标记;对于post请求,有body,使用Content-Length记录body的长度。


2.2.9 核心特性十——异常情况的处理 

在TCP中存在以下几种特殊情况:

<1>进程奔溃:和主动退出没有本质区别,都是是使进程释放,回收文件描述符表的每个资源(即调用socket的close方法),就会正常触发四次挥手(进程没了,但是TCP连接还在)

<2>主机关机(正常关机):本质上还是先杀死所有的进程,如果在关机前,四次挥手结束了,就是和<1>的情况相同;如果没有结束:

<3>主机掉电

   1.接收方掉电

   2.发送方掉电

<4>网线断开:站在接收方视角,就是发送方掉电

                        站在发送方视角,就是接收方掉电

 

标签:ACK,IP,报文,TCP,交通规则,发送,数据包,应答
From: https://blog.csdn.net/zhakakqns/article/details/144921972

相关文章

  • 【网络协议】IPv4 地址分配 - 第一部分
    文章目录十进制与二进制网络如何被寻址地址类型网络地址广播地址主机地址如何确定网络和主机部分的位数?网络中的主机数量与前缀号的关系计算每个前缀的主机数量公式子网掩码二进制与操作(BinaryANDing)与操作(ANDOperation)二进制与操作的结果关于子网划分为什么要进行......
  • Javascript中的return你了解多少?
     目录1、 js中对于return用法的三种情况的总结如下:2、return的特点......
  • javasript DOM基础学习
    DOM简介1.1什么是DOMDOM是一个处理可扩展标记语言(HTML、XML)的接口,可以改变网页的内容、结构和样式1.2DOM树文档:一个页面就是一个文档,DOM中使用document表示元素:页面中所有的标签都是元素,DOM中使用element表示节点:网页中所有的内容都是节点(标签、属性、文本、注释等),DOM中使......
  • 深入解析DNS、VPC、共享带宽包、负载均衡和IP的异同与配合使用
    个人名片......
  • 如何处理服务器IP地址更改后无法登录的问题
    用户反馈在将服务器IP地址更改为域名登录后,出现无法登录的情况。用户不确定是配置问题还是服务器问题。解决方案:服务器IP地址更改后无法登录的原因可能涉及多个方面,以下是详细的排查步骤:检查配置文件:确保服务器的配置文件中已正确更新为新的域名。例如,对于Linux服务器,可以检......
  • CanvasContext.clip
    CanvasContext.clip()CanvasContext是旧版的接口,新版Canvas2D接口与Web一致从基础库2.9.0开始,本接口停止维护,请使用RenderingContext代替基础库1.6.0开始支持,低版本需做兼容处理。小程序插件:支持相关文档:旧版画布迁移指南、canvas组件介绍功能描述从......
  • 28 个 JavaScript 单行代码让你成为 JavaScript 大神
    1.反转字符串constreversedString=str=>str.split('').reverse().join('');reversedString("HelloWorld");//dlroWolleH此函数获取一个字符串,将其拆分为一个字符数组,反转该数组,然后将其重新合并为一个字符串,反转原始字符串。2.标题大小写字符串consttitle......
  • JavaScript 观察者模式:前端开发必备技能
    一、什么是观察者模式?        观察者模式(ObserverPattern),也称为发布-订阅模式(Publish/Subscribe),定义了一种一对多的依赖关系。当一个对象(被观察对象或主题Subject)的状态发生变化时,所有依赖于它的对象(观察者Observer)都会得到通知,并自动进行相应的更新。     ......
  • 在TypeScript中枚举和常量枚举有什么区别?
    在TypeScript中,枚举(Enums)和常量枚举(ConstEnums)都是用于定义一组命名的常量值的数据类型。然而,它们在编译时的行为和使用上存在一些关键差异。1.枚举(Enums)枚举是TypeScript提供的一种特殊的数据类型,它允许我们为一组数值定义友好的名字。默认情况下,枚举中的第一个成员被赋......
  • 在TypeScript中如何实现继承?
    在TypeScript中,可以通过extends关键字来实现类的继承。以下是一个简单的示例:classAnimal{name:string;constructor(name:string){this.name=name;}speak(){console.log(`${this.name}makesanoise.`);}}classDogext......