TCP粘包
为什么说TCP是面向字节流的协议,UDP是面向报文的协议?
原因在于两者发送方的机制不同,UDP传输时,系统不会对报文进行拆分,在封装好UDP头部后就会交给网络层,所以发出去的UDP报文就是完整的一个消息,也就是每个UDP报文就是一个消息的边界。而TCP协议则会对发出消息拆分成多个报文,如果接收方不知道发送方的消息长度,就不知道消息的边界,无法读取有效的消息,因此TCP传输不能认为一个用户消息对应一个TCP报文,所以说TCP是面向字节流的协议。
当两个消息的部分内容被分到同一个TCP报文,就出现了粘包,这时接收方不知道消息的边界的话,无法读出有效的消息。解决方式在于如何分包,确定消息边界。一般有三种方式分包的方式:
- 固定长度的消息:每个消息长度固定,但该方式灵活度不高
- 特殊字符作为边界:两个用户消息之间插入特殊字符,如果刚好消息内容里有这个特殊字符,那么要在发送时对这个字符转义,避免被接收方当作消息的边界点而解析到无效的数据。
- 自定义消息结构:我们可以自定义一个消息结构,由包头和数据组成,其中包头包是固定大小的,而且包头里有一个字段来说明紧随其后的数据有多大。