[JavaEE] TCP协议
目录
一、TCP协议段格式
二、TCP确保传输可靠的机制
2.1 确认应答
2.2 超时重传
2.3 连接管理
2.3.1 三次握手
2.3.2 四次挥手
2.4 滑动窗口
2.4.1 基础知识
2.4.2 两种丢包情况
2.4.2.1 数据报已经抵达,ACK丢包
2.4.2.2 数据包丢包
2.5 流量控制
2.6 拥塞控制
2.7 延迟应答
2.8 捎带应答
2.9 面向字节流
三、异常情况
3.1 进程终止
3.2 机器重启
3.3 机器掉电/网线断开
一、TCP协议段格式
TCP全称为"传输控制协议(Transmission Control Protocol")。
源/目的端口号:标识数据是从哪个进程来,到那个进程去;
4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节,单位是4字节)
6保留位:为后续的可拓展性留下的没被启用的空间
6标志位:
URG:紧急指针是否有效
ACK:确认号是否有效
PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
RST:对方要求重新建立连接,RST标识的被称为复位报文段
SYN:请求建立连接;SYN标识的被称为同步报文段
FIN:通知对方,本端要关闭了,FIN标识的被称为结束报文段
16位校验和:发送端填充,通过CRC校验,如果接收端校验不通过,则认为数据有问题,包含TCP首部和数据部分。
16位紧急指针:标识那部分数据是紧急数据
二、TCP确保传输可靠的机制
2.1 确认应答
在接收方收到数据之后,就要给发送方返回一个“应答报文”(ack/acknowledge)。
在网络信息传输中,由于每个信息所通过的传输路径不相同,所以可能造成,后发的信息早于先发的信息到达接收端,我们把这个现象叫做“后发先至”。针对于这个现象,TCP中通过针对信息进行“编号”方法解决。
TCP面向字节流,所以编号的排序是按照字节来排,且字节之间是连续递增的,这种按照字节排序的机制,就叫做“TCP的序号”,在应答报文中,针对接受之前数据的排序的机制,就叫做“确认序号”。
丢包:数据传输的过程中,可能会发生bit翻转,接受方接受这个数据发现校验和对不上了,就会把这个数包丢弃。也可能是数据传输到某个节点,这个节点负载过高的时候,就会发生丢。
针对上方提到的丢包现象,TCP为了确保传输的可靠性,接收方会有一个“接受缓冲区”,接收方接收到数据,先进入到缓冲区里,后续再接收到数据,就会根据序号在缓冲区中排序,如果发现有重复的现象,缓冲区就会自动去掉重复的数据。
2.2 超时重传
超时重传,这里的超时指的并不是时间,而是动态变化的。第一次传的时候花费t1时间,如果长时间没有ack就会发送第二次,花费的时间t2>t1,每次重传的时候时间就会增加,如果重传多次之后都没有ack,这时TCP就会发送一个特殊的数据包“复位报文”,再次建立连接重新连接,使通信可以继续进行,如果复位报文没有得到回应,这时TCP就会单方面放弃连接。
2.3 连接管理
2.3.1 三次握手
在连接前,客户端会发送一个没有业务的数据包,也就不包含任何数据,只有TCP报头。在客户端发送syn同步请求之后,服务器接收之后也会发送一个ack+syn来回应客户端,客户端收到服务器发送的syn请求之后,会发送一个ack返回给服务器。
三次握手的意义:
投石问路,初步验证信息的链路是否通畅,是可靠传输的“前提条件”,确认双方各自的接受和发送能力正常。
这个过程也需要确定TCP序号开始的大小,这样做的意义就是为了避免,一个数据包走丢的过久,导致传输到服务器的时候已经不需要了。
协商参数,通信双⽅共同确认⼀些通信中的必备参数数值。
2.3.2 四次挥手
双方各自把对端的信息删除,简略过程如下图,这里面不同于“三次握手”需要发送四次,因为ack是由系统内核所发出的,而FIN是由程序经过逻辑代码发出的,所以需要分两次发送。
TCP的几个状态转化
1.LISTEN:服务器的状态,服务器好绑定端口,表示可以建立连接。
2.ESTABLISHED:客户端和服务器的状态,表示建立完结完毕(保存好对方信息)。
3.CLOSE_WAIT:被动断开连接的一方,也就是先收到FIN的一方(等待代码执行close方法)。如果服务器存在大量CLOSE_WAIT状态的TCP连接,说明调用close方法出现问题。
4.TIME_WAIT:客户端接收到服务器的ACK和FIN之后,按照时间来等待,达到一定状态之后释放连接,因为存在客服端发送ACK丢包的现象,所以需要等待一段时间。如果保存一段时间之后,没有收到重传FIN,说明ACK没有丢包,也就会释放连接。
TIME_WAIT存在的时间,成为2MSL,不同系统不一样,是可配置的。
2.4 滑动窗口
2.4.1 基础知识
刚才我们讨论了确认应答策略,对每⼀个发送的数据段,都要给⼀个ACK确认应答。收到ACK后再发送下 ⼀个数据段。这样做有⼀个⽐较⼤的缺点,就是性能较差,尤其是数据往返的时间较⻓的时候。
窗口大小:把“发送一次等待一个”改进为“发送一批等待一批”,批量发送数据,不需要等待的数据的量,成为“窗口大小”,批量发送的单位是字节。
如上图发送前四个段的时候,不需要等待任何ACK,直接发送;
收到第一个ACK后,滑动窗口向后移动一个单位,继续发送第五个段的数据;
操作系统为了维护这个滑动窗口,需要开辟发送缓冲区,来记录当前还有哪些数据没有应答,只有确认应答过的数据,才能从缓冲区删除;
窗口越大,网络的吞吐率就越高。
2.4.2 两种丢包情况
2.4.2.1 数据报已经抵达,ACK丢包
ACK丢包并不要紧,因为后面的ACK包括前面的,可以通过后面的ACK是否发送来进行确认。
2.4.2.2 数据包丢包
快速重传:上图中,快速识别哪个数据包丢包之后,并且针对性的重传,其他顺利到达的数据无需重传,这个过程被称为“快速重传”
2.5 流量控制
TCP⽀持根据接收端的处理能力,来决定发送端的发送速度。这个机制就叫做流量控制(Flow Control)。
接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等⼀系列连锁反应。窗口大小并不是越大越好,针对于确定窗口大小的合理大小,TCP内有流量控制机制。接收方有接收缓冲区,根据序号排序并且去重,并且向发送方反应缓冲区的剩余空间是否过小。
接受端将自己的可以接受的缓冲区大小放入TCP首部中的“窗口大小”字段,通过ACK端通知发送;
窗口大小字段越大,说明网络的吞吐量越高;
接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端;
发送端接收到这个窗口之后,就会减慢自己的发送速度;
如果接收端缓冲区满了,就会将窗口设置为0,这是发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。
由于TCP首部中,只有一个16位窗口字段,我们所传输的最大上限是固定的,TCP为了解决这个问题,在首部选项中包含了一个窗口扩大因子M,实际窗口大小是 窗口字段的值左移M位;
2.6 拥塞控制
在接收端有流量控制的机制,可是一旦发送方开始就大量的发送数据,可能会造成路由器的阻塞,而导致频繁丢包的现象。为了解决发送方的问题,TCP引入了一个慢启动机制,先发送少量的数据,再决定按照多大的速度传输数据。
此处引入一个概念程为拥塞窗口,发送开始的时候,定义拥塞窗口大小为1,每次收到一个ACK应答,拥塞窗口增加1。每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小 做比较,取较小的值作为实际发送的窗口。
像上面这样的拥塞窗口增长速度,是指数级别的,“慢启动”知识初始时慢,但是增长非常快。
为了不增长那么快,引入一个叫慢启动的阈值,当拥塞窗口超过这个阈值的时候,不再按照指数指数方式增长,而是按照线性方式增长。当TCP开始启动的时候,慢启动阈值等于窗口最大值,在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置为1.
2.7 延迟应答
如果直接接受数据的主机直接返回ACK的应答,这时候返回的窗口可能比较小,如果稍慢一下返回ACK应答,有可能经过这一小段时间之后,空间就变大了。当然,并不是一定空间会变大,也有可能由于发送发发送的数据量大于接收方处理的能力,就会造成延时应答之后空间变小。
数据多的时候:每隔N个包就应答一次;
数据少的时候:通过时间限制,超过最大延时时间就应答一次。
一定要记得,窗口越大,网络吞吐量就越大,传输效率就越高。我们的目标是在保证网络不拥塞的情况下尽量提高传输效率。
2.8 捎带应答
在延时应答的基础上,我们可以将两个不同时间发送的数据一起返回。比如在四次握手的情况下,由于ACK是由系统内核所发,一定快于由程序逻辑所发的FIN,所以我们可以在延时应答的基础上,让ACK和FIN一起返回。
2.9 面向字节流
粘包问题
•首先要明确,粘包问题中的“包”,是指应用层的数据包
•在TCP协议头中,没有同UDP一样的“报文长度”这样的字段,但是有一个序号这样的字段。
•站在传输层的角度,TCP是一个一个报文过来的,按照序号排好序放在缓冲区中。
•站在应用层的角度,看到的只是一串连续的字节数据,
•那么应用层看到了这一传字节数据,不知道如何分割,才是一个完整的应用层数据包
所以为了避免粘包问题,需要明确两个包之间的边界
•方案一:指定分隔符
•方案二:指定数据的长度
•方案三:可以在包头的位置,约定⼀个包总⻓度的字段,从⽽就知道了包的结束位置。
对于UDP协议来说不存在“粘包问题”,因为一个DatagramSocket就是一个完整的应用层数据报。
三、异常情况
3.1 进程终止
进程终止会释放文件描述符,仍然可以发送FIN,和正常关闭没有什么区别。
3.2 机器重启
和进程终止情况相同。
3.3 机器掉电/网线断开
发送方掉电:TCP自己也内置了一个保活定时器,接收端会发送一个探测报文“心跳包”,定期询问对方是否还在,如果对方不在,也会把链接释放。
接收方掉电:发送方会触发超时重传,一定次数之后还没有发送到,会单方面释放连接。
=========================================================================
如果对你有用的话,请给博主一个三联,博主会继续努力的ヾ(◍°∇°◍)ノ゙