TCP报文

目录

一.报头

二.TCP内部工作机制

1.确认应答

2.超时重传

特点

小结

3.连接管理*

建立连接过程(三次握手)

断开连接过程(四次挥手)

4.滑动窗口 

5.流量控制

6.拥塞控制

7.延时应答

8.捎带应答

9.面向字节流

10.异常情况       


一.报头

源端口和目的端口号:各两个字节。

序号:任何一条数据都是有序号的,而TCP是面向字节流的,每个字节都会编号,如果一条数据是1000个字节,假设从1开始编号(实际上会有协商的过程),第一个字节是1,而这1000个字节都属于同一个TCP报文,TCP报文里只记录第一个字节的序号,那接下来第二条数据的头一个字节就是1001,知道了头字节的序号,再根据TCP报文长度,就能知道每个字节的序号。32位。

确认序号:只有应答报文才有,确认序列号,意思是告诉发送者,我已经收到了哪些数据;下一次你从哪里开始发,普通报文里的确认序号里的值无意义,用于辨别该应答报文与那条数据对应,32位。

头部长度:表示TCP报头的长度,一个TCP报头的长度是可变的,4位(范围0~15),此处单位为4字节,即头部长度为5,代表报头总共20字节

保留:总共6位,主要是用于未来的扩展考虑的,后续引用新的功能,可以使用保留值,降低成本,提高兼容性。

六个标志位:ACK为1表示此报文为应答报文,0则表示不是。


二.TCP内部工作机制

主要讨论TCP提供的10个主要的核心机制。

1.确认应答

        TCP是一种可靠传输,最主要就是通过应答机制来实现的。当A给B发了一个信息,B收到信息后就会返回一个应答报文ACK,A收到应答报文后,就知道发送的信息已经顺利达到B。

        但是由于网络存在“后发先至”的情况(两个主机之间,可能会存在多条路线),所以通信双方可能收到的信息顺序是存在变数的,如果现在同时A发送了两条信息,那B返回两个ACK,判断这两个ACK与那条信息对应是很困难。要解决这种问题,就需要给传输的数据和应答报文进行编号,通过序号和确认序号,就可以判断当前的应答报文是针对那一条数据进行的了


2.超时重传

        确认应答是建立在顺利传输的基础上进行讨论的,但在实际的网络传输中,很可能发生丢包的情况。此处的丢包涉及到两种可能:1.发送的数据丢失;2.返回的ack丢失。

        超时重传就是描述传输出现问题的情况,在丢包后,会再次发送同样的数据。但是怎么确认是丢包了,还是ack传输太慢还没有返回呢?TCP又引入了一个时间阈值(这个时间是可配置的)发送方发送数据后,开始计时,如果在超过了时间阈值都没有收到ack,那就不论是丢包还是ack正在传输,都视为丢包。

        但是这样一来,又产生了新的问题,由于ack返回太慢,超过了时间阈值,发送方就会再此发送数据,如此,接收方就收到同一数据两次。在一些场景下,这可能就会发生严重后果。那么该如何解决这个问题呢?TCP对于这种重复数据的传输,会进行去重处理。每个TCP对象socket都存在一个接收缓冲区(可视为一个阻塞有序队列),接收方收到数据,会把数据存放在接受缓冲区内,后续应用程序进行读数据,也是直接读缓冲区的数据。如此一来,在缓冲区内,可以根据数据的序号,判断两条数据是否重复,如果重复了,就把后加入的数据丢弃。同时,TCP还可以利用缓冲区对所以数据进行排序,使得数据与发送顺序一致。       

特点

        超时重传不会无限进行,重传多次后,仍没传输成功,此时继续重传意义便不大了,就不会继续重传,认为网络故障,TCP会尝试断开重连,如果重新连接还失败,就彻底断开连接。

        重传的时候,第一次重传和第二次重传的时间阈值不同,重传轮次越大,时间间隔越大

小结

TCP的可靠传输就是通过确认应答和超时重传来体现的,这两者相互配合,共同支撑TCP的可靠性,可靠性是TCP最核心的特点。


3.连接管理*

连接本质上是某个主机存储对端主机的相关信息。

TCP过程图:

其中除了TIME_WAIT的等待时间为2msl,其他交互的等待时间都随着超时重传的时间阈值。

建立连接过程(三次握手)

建立连接的过程实际上了发送方与接收方各自向对方发送一个建立连接的请求,并回应一个应答。站在发送及接收的视角上来说,必须满足双方都发送连接请求,并收到对方的应答之后,才算建立连接

如下图:

简述TCP三次握手和四次挥手_洒家肉山大魔王的博客-CSDN博客_简述tcp三次握手四次挥手

所谓三次握手,本质是四次交互,但中间的两次交互可合并,所以称为三次握手。

为什么中间两次请求一定要合并呢?

        在网络传输中,涉及对每个层级的封装分用,封装分用是具有开销的,所以此处一定会合并为一条信息。

        三次握手还可以验证通信双方各自的发送能力和接收能力是否正常。一次成功的建立连接,可以让一方知道自己的收发能力是否正常,以及对方的收发能力是否正常。第一次交互:发送方发送SYN(同步报文段),如果到达接收方,此时接收方知道了发送方的发送能力正常;第二次交互:SYN/ACK到达发送方,发送方知道了自己的收发能力正常,以及接收方的收发能力正常;第三次交互:ACK到达接收方,接收方知道了自己的收发能力正常,以及发送方的接收能力正常。

三次握手的意义:

1.让通信双方各自建立对对方的认同;

2.验证通信双方各自的发送能力和接收能力是否正常;

3.在握手过程中,双发协商一些重要的参数(比如开始计数序号)。

断开连接过程(四次挥手)

四次挥手与三次握手相似,都是通信双方各自向对方发送一个断开连接请求,再各自返回一个应答。

具体过程如下图:

简述TCP三次握手和四次挥手_洒家肉山大魔王的博客-CSDN博客_简述tcp三次握手四次挥手

那此处中间的两次交互ACK和FIN能否合并呢?

        这两次能否合并取决于二者的时机是否相同。像三次握手它之所以可以合并是其SYN/ACK是在同一时机发生的(三次握手的过程是在内核中完成的,应用层面无法感知,服务器的内核收到SYN后,就会立即发送ACK和SYN)。而在四次挥手过程中,FIN的发起,是由应用程序调用socket.close方法或进程退出所触发的,ACK是由内核控制,内核收到FIN后,立即返回ACK,那么第二次FIN与第一次ACK之间就存在一个由代码决定的时间间隔,如果发送FIN和收到FIN的时间间隔很短,则会合并一起发送。

两个重要的TCP状态

CLOSE_WAIT

出现在被动发起断开连接的一方,等待调用close方法关闭socket,发送FIN.

TIME_WAIT

        出现在主动断开连接的一方,为了保证主动方暂时不要断开TCP连接。因为如果最后一个ACK丢包了,那么被动方也就无法知道是自己发送的FIN丢了,还是ACK丢了。这就会触发超时重传,此时如果主动方断开连接,就无法做出ACK响应,因此TIME_WAIT存在的目的就是解决最后一次ACK丢包的情况。TIME_WAIT会等,但在一段时间后,没收到重传就会视为最后一个ACK没丢,于是彻底的释放连接。

        TIME_WAIT最大保持时间,约定为2MSL(为互联网中,两个节点传输的最大时间)。


4.滑动窗口 

        滑动窗口的本质是不等待批量发送一组数据,然后用一份时间等待一组数据的多个ACK。 把不需要等待可发送的数据最大的量,称为窗口大小。

        批量发送数据后,发送方需要等待ACK,此时并不是等待所以ACK都到达,才继续发送,而是到一个ack就继续往下发一条。

        滑动窗口必须是连续的,如下图:

如果在传输中发送丢包?

1.数据包到达,ACK丢了

这种情况一般不做任何处理,因为TCP的确认序号由一种特殊的含义,接收方能返回ack就代表其序号之前的所有数据都已经成功到达了,虽然中间某一条数据的ack丢了,但只要之后有更高序号的ack成功发送,都视为数据成功达到。 

2.数据包丢了

如果数据包丢了,实际会发生以下过程:

实质上,会进行快速重传。如上图:1-1000字节的数据丢失去了,那么B就会一直返回1001的ACK,主机A会继续正常向下发送数据,但当收到了3个同样的确认应答时,就会根据这个重复的ACK进行重传1-1000的数据,当B收到了1-1000的数据,就会判断接下来1001-2000是否达到,以此向下判断,最后返回到达的最高序号的ACK即7001,此时就代表7001之前的所有的数据都到达了,主机A收到1001的ACK后,也会在接收缓冲区内进行按序号排序。如果7001之前还有一组数据2001-3000丢失了,那么当1001的ACK达到A后,B就会返回2001的ACK,重复以上步骤。


5.流量控制

        流量控制主要是针对滑动窗口的大小进行调节。如果滑动窗口过大,但是接收方的接收能力有限,此时就需要减小窗口的大小,反之则增大,所以流量控制主要工作就是根据接收方的处理能力,通过动态调整窗口大小,来协调发送方的发送速率。

如何衡量接收方的处理能力?

        直接根据接收方接收缓冲区的剩余大小判断,而这个大小参考于为ACK报文返回的16位窗口大小。16位的窗口大小不意味着窗口最大为64KB,在TCP报文的选项部分,引入了窗口扩展因子,如果窗口扩展因子为2,则表示让64KB<<2 = 》256KB。

        随着数据的发送,但没有ACK返回,窗口将会变小,当窗口大小为0时,发送方就会暂停发送。但是暂停的时间内,发送方会给接收方定期发送窗口探测报文,此报文不携带具体的业务数据,只是为了触发ACK查询窗口大小。


6.拥塞控制

        拥塞控制和流量控制共同决定发送方的窗口大小。而流量控制考虑的是接收方的处理能力,拥塞控制描述传输过程中,中间节点的处理能力。

窗口变化过程:

 刚开始,初始窗口较小,每一轮不丢包会使窗口扩大一倍,即呈指数增长,当增长速率达到阈值后,指数增长变为线性增长(前提是不丢包),一旦发送了丢包,说明此时的发送速率已经很接近网络的极限,此时将把窗口大小置为很小的值并重复以上指数与线性增长的过程。拥塞窗口不是固定数值,而是处于动态的变化当中,随着不断的循环,逐渐到达一个动态平衡的过程,这样就能随着网络的动态变化而变化。


7.延时应答

        延时应答也是基于滑动窗口来提高效率。滑动窗口大小越大,传输效率就越高。所以延时应答就是尽可能充分利用接收方的处理能力,在收到数据之后,接收方不是立即返回ACK,而是等待一段时间,在这一段时间内,接收方将接收缓冲区内的数据进行处理,这样缓冲区内的剩余空间就更大,因此返回的ACK就可以告诉发送方调大窗口的大小。 

        在实际表现上,就是在滑动窗口下,ack不是每一条数据都会返回,而是隔一条或几条再返回。


8.捎带应答

        捎带应答是基于延时应答来完成的一种提高效率的机制。如果主机A和主机B之间存在互相发送请求的逻辑,那么当A发送请求给B后,恰好此时,B正好也有请求要发给A,由于存在捎带应答机制,此时ACK和请求可以合并一起发送给A了。而之前的延时应答,能提高捎带应答发送的概率。


9.面向字节流

        由于TCP面向字节流,所以存在“粘包问题”,即当接收缓冲区接收到多个数据后,应用程序read时,可能读一整个完整的应用层数据包,也可能读半个。所以要解决“粘包问题”,就需要程序员在应用层约定好应用层协议,即明确数据包之间的边界。可以采用分隔符来区分,也可以在在数据前加上数据的长度。如在TCP实现回显服务器时,使用printwriter.println即是加上‘\n’分隔符。


10.异常情况        

        在实际工作时,主机可能会发生关机和线程崩溃,断电和断网等异常情况。

        线程崩溃和主机关机(正常关机),进程没了,对应PCB就没了,相应的文件描述符表就释放,内核是会完成4次挥手的操作的。但断电和断网来不及进行断开连接操作,如果是接收方发生了这种异常,发送方等不到ACK,就会超时重传,重传几次,还没有响应会尝试重连(复位报文段,PST),最后放弃连接。如果是发送方的话,接收方不知是发完了,还是发送方等会再发,就会先等,并周期性发送消息(心跳包机制),确认对方是否正常,这种保活机制来确认通信双方是否处于正常工作状态。

以上就是TCP的所有介绍。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

todd1er

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值