深入解析TCP粘包/拆包问题及序列化

3.TCP粘包/拆包问题

1.TCP粘包/拆包问题说明

  1. TCP是个流协议。底层并不了解上层业务数据的具体含义,所以一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送。这个是粘包/拆包问题。
  2. 所以服务端TCP接收滑窗非常小,而数据包非常大,很有可能要分多次才能接收完全,期间发生多次拆包。

2.TCP粘包/拆包发生的原因

  1. 应用程序write写入的字节大小大于套接口发送缓冲区大小。
  2. 进行MSS大小的TCP分段。
  3. IP层要传的数据大于MTU进行IP分片。

3.粘包问题的解决策略

  1. 由于底层TCP无法理解上层的业务数据,所以只能通过上层的应用协议栈设计来解决:
    (1)消息定长。
    (2)在包尾增加回车换行符进行分割。例如FTP协议。
    (3)将消息分为消息头和消息体,消息头中包含表示消息总长度的字段,通常使用int32.
    (4)更复杂的应用层协议。

4.利用LineBasedFrameDecoder和StringDecoder解决粘包/拆包问题

  1. 对于使用者,只要将支持半包解码的Handler添加到ChannelPipeline中即可,不需要写额外的代码
  2. LineBasedFrameDecoder的工作原理是它依次遍历ByteBuf的可读字节,判断看是否有换行字节,如果有,就以此位置为结束位置。从可读索引到结束位置区间的字节就组成了一行。它是以换行符为结束标志的解码器,支持携带结束符或者不携带结束符2种解码方式,同时支持配置单行的最大长度。
  3. StringDecoder就是将接收到的对象转换成字符串,然后继续调用后面的Handler。

4.分隔符和定长解码器的应用

  1. DelimiterBasedFrameDecoder:通过自定义分隔符来区分数据包。
  2. FixedLengthFrameDecoder:无论一次接受到多少数据报,它都会按照构造函数中设置的固定长度进行解码,如果是半包消息,FixedLengthFrameDecoder会缓存半包消息并等待下个包到达后进行拼包,直到读取到一个完整的包。

5.序列化

1.Java序列化

  1. 基于Java提供的对象输入/输出流,可以直接把Java对象作为可存储的字节数组写入文件,也可以传输到网络上。基于JDK默认的序列化机制可以避免操作底层的字节数组。
  2. Java序列化的缺点:
    (1)无法跨语言。
    (2)序列化后的码流太大
    (3)序列化性能太低
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值