Netty一、TCP粘包、拆包问题

1 TCP 粘包、拆包

TCP是一个流式协议,没有边界。TCP底层会按照TCP缓冲区内情况进行包的拆解,合并,就会产生粘包,拆包问题。

1.1 产生粘包、拆包的原因

  1. 应用程序 write 的字节大小大于缓冲区大小
  2. 进行 MSS 大小的TCP分段
  3. 以太网帧的 payload 大于MTU 进行 IP 分片

1.2 解决方案

  1. 消息定长

每次发送消息固定长度,不足长度空格补上,但是浪费空间

  1. 消息末端增加换行符进行消息切割

FTP协议

  1. 将消息分为消息头为消息体,消息头包含消息长度

2. netty 提供的解决方案(编码解码器)

  1. LineBasedFrameDecoder (换行符解码器)

A decoder that splits the received {@link ByteBuf}s on line endings.Both {@code “\n”} and {@code “\r\n”} are handled.

原理是依次遍历 ByteBuf 中的字节,直到读到换行符,丛可读位置到结束位置就组成一行内容。

构造器支持设定大小,当超过大小仍没有读到换行符,则被认为为异常消息内容,同时忽略掉之前读到的流。

@Override
protected void initChannel(SocketChannel ch) throws Exception {
    // 换行符解码器   
    ch.pipeline().addLast(new LineBasedFrameDecoder(1024));
    ch.pipeline().addLast(new StringDecoder());
    ch.pipeline().addLast(new NettyServerHandler());
}
  1. DelimiterBasedFrameDecoder (分隔符解码器)

A decoder that splits the received {@link ByteBuf}s by one or more * delimiters.

用一个或多个*分隔符分割接收到的{@link ByteBuf}的解码器。

@Override
protected void initChannel(SocketChannel ch) throws Exception {
    // 分隔符解码器
    ByteBuf byteBuf = Unpooled.copiedBuffer("$_".getBytes());
    // 第一个参数 1024 标识单条消息最大长度,达到最大长度后还没有找到分隔符,就抛出TooLongFrameException
    // 第二个参数为缓冲区分割对象
    ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, byteBuf));
    ch.pipeline().addLast(new StringDecoder());
    ch.pipeline().addLast(new NettyServerHandler());
}
  1. FixedLengthFrameDecoder(定长解码器)

A decoder that splits the received {@link ByteBuf}s by the fixed numbe * of bytes.

将接收到的{@link ByteBuf}按固定的字节数分割。

@Override
protected void initChannel(SocketChannel ch) throws Exception {
    // 定长解码器 会按照构造函数内的大小进行数据读取
    ch.pipeline().addLast(new FixedLengthFrameDecoder(100));
    ch.pipeline().addLast(new StringDecoder());
    ch.pipeline().addLast(new NettyServerHandler());
}

3. xmind

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值