今天在面试过程中被问到了TCP的粘包问题,自己回答的不是很好,所以在这里总结一下这个问题。
1.什么是TCP粘包
发送方发送的若干数据,在接受方接受时这些数据粘在了一起(一包)。从接收缓冲区来看,后一包数据的头紧接着前一包数据的尾。 这种现象被称作TCP的粘包问题。
2.发生TCP粘包的原因
1.发送方
发送端为了将多个发往接收端的包,更加高效的的发给接收端,于是采用了优化算法(Nagle算法),将多次间隔较小、数据量较小的数据,合并成一个数据量大的数据块,然后进行封包。
而Nagle算法是造成发送方出现沾宝问题的主要原因。
2.接收方
TCP接收到数据包时,并不会马上交到应用层进行处理,或者说应用层并不会立即处理。实际上,TCP将接收到的数据包保存在接收缓存里,然后应用程序主动从缓存读取收到的分组。这样一来,如果TCP接收数据包到缓存的速度大于应用程序从缓存中读取数据包的速度,多个包就会被缓存,应用程序就有可能读取到多个首尾相接粘到一起的包。
3.粘包问题的解决方法
1.对于发送方
可以通过编程设置来关闭Nagle算法,使用TCP提供的强制数据立即传送的操作指令push。但这样会降低发送效率,影响程序性能,所以这个方法并不推荐使用。
2.对于接收方
只能通过优化程序设计等措施保证接收方及时接收数据。但这种方法只能减少粘包出现的可能性,并不能完全防止粘包问题的发生,所以并不能算做成一个解决方案。
3.应用层
应用层的解决办法简单可行,不仅能解决接收方的粘包问题,还可以解决发送方的粘包问题。
解决办法:循环处理,应用程序从接收缓存中读取分组时,读完一条数据,就应该循环读取下一条数据,直到所有数据都被处理完成,但是如何判断每条数据的长度呢?
格式化数据:每条数据有固定的格式(开始符,结束符),这种方法简单易行,但是选择开始符和结束符时一定要确保每条数据的内部不包含开始符和结束符。
发送长度:发送每条数据时,将数据的长度一并发送,例如规定数据的前4位是数据的长度,应用层在处理时可以根据长度来判断每个分组的开始和结束位置。
P.S:UDP是面向消息传输的,是有保护消息边界的,接收方一次只接受一条独立的信息,所以不存在粘包问题。