TCP/UDP协议深度解析(四):TCP的粘包问题以及异常情况处理


🔍 开发者资源导航 🔍
🏷️ 博客主页个人主页
📚 专栏订阅JavaEE全栈专栏

本系列往期内容~

TCP/UDP协议深度解析(一):UDP特性与TCP确认应答以及重传机制

TCP/UDP协议深度解析(二):TCP连接管理全解,三次握手四次挥手的完整流程

TCP/UDP协议深度解析(三):TCP流量控制的魔法---滑动窗口、拥塞控制与ACK的智慧

一、 粘包问题

因为TCP协议是面向字节流的,因此接收方收到的数据是一段连续的数据,接收方无法判断那一段数据是一个整体,这一段连续的数据就像是"粘"在了一起,无法区分,而这就称之为"粘包问题"。

1.1 解决方法

该问题在传输层层面无解,想要解决这个问题需要站在应用层角度来解决。

1.约定包与包之间的分隔符

约定某一个字符作为该段数据的结束标志,例如使用换行符'\n'。

2.约定包的长度或格式

例如:约定包的前n个字节表示数据的长度 。

解决粘包问题是在自定义应用层格式的时候要考虑的问题,但是已经存在成熟的解决方案,例如:json、protobuf等,因此不必过多操心该问题。

二、TCP连接时的异常情况处理

2.1 进程崩溃

四次挥手的进行并不依赖进程,因此如果某个进程崩溃,它和正常退出没有本质区别,并不会出现异常情况。

2.2 主机关机

正常的关机都会先杀死用户的进程,但是关机也需要一定的时间,如果这段时间内挥手结束,那么就和正常一样,如果这段时间没有挥完也是可以将连接释放掉的。

2.3 接收方掉电

如果接收方掉电,发送方发送的信息将不会再收到ack,此时无论多少次的超时重传都无法解决问题,当达到一定次数后,发送方会主动发送一个"复位报文",重置TCP连接,如果还是收不到ack,那么发送方就会主动释放掉连接。

2.4 发送方掉电

如果发送方突然掉电了,接收方因为是被动的一方,无法确认对方现在是休息了还是挂掉了,因此他只能等待下去,但是并不会无限等待,超过一定的时间后会主动的发送"心跳包",来确认对方的状况。

心跳包并不包含载荷,他只是为了触发对方的ack,如果没有心跳就认为对方挂掉了,进行RST复位,再不行就会释放掉该连接。