Netty 粘包 & 半包

TCP 是面向流的,提供高可靠性服务。收发两端都要有成对的 Socket

因此发送端为了将多个发给接收端的包,更有效的发送给对方,使用了 Nagle 算法优化

将多次间隔较小且数量小的数据,合并为一个大的数据块,然后进行封包,

这样虽然提高了效率,但是接收端就难以分辨出完整的数据包了,因为面向流的通信是无消息保护边界的

粘包

现象

发送 abc def,接收为 abcdef

原因

  • 应用层:接收方 ByteBuf 设置太大(Netty默认1024)
  • 滑动窗口:假设发送方256bytes表示一个完整的报文,但由于接收方处理不及时且窗口大小足够大,这256bytes字节就会缓冲在接收方的滑动窗口中,当滑动窗口中缓冲了多个报文就会出现粘包
  • Nagle 算法

半包

现象

发送 abcdef 接收 abc de f

原因

  • 应用层:接收方 ByteBuf 小于实际发送数据的数量

  • 滑动窗口:加涉接收方的窗口只剩128bytes,发送方的报文大小是256bytes,这时放不下了,只能先发送前128bytes,等待ack后才能发送剩余部分,这就造成半包

  • MSS限制:当发送的数据草果 MSS 限制后,会将数据切分发送,就会照成半包

粘包半包演示

服务端

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        logger.info("客户端发送的消息是 : {}", buf.toString(CharsetUtil.UTF_8));
    }
复制代码

客户端

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        for (int i = 0; i < 10; i++) {
            ByteBuf buf = Unpooled.copiedBuffer("Hello Client" + i, CharsetUtil.UTF_8);
            ctx.writeAndFlush(buf);
        }
    }
复制代码

结果打印

[nioEventLoopGroup-3-1] INFO io.mvvm.netty.decoder.NettyServerHandler - 客户端发送的消息是 : Hello Client0Hello Client1Hello Client2Hello Client3Hello Client4Hello Client5Hello Client6Hello Client7Hello Client8Hello Client9
复制代码

结论

代码解释

客户端和服务端建立连接后,循环向服务端发送10条消息

期望结果

服务端收到10条消息

实际结果

服务端将10条消息放在一起成为了一条消息,这就是粘包现象

解决方案

短连接

建立连接后只发送一次消息,发送消息完毕后断开连接

缺点:不如用http

定长解码器 FixedLengthFrameDecoder

定常解码器即固定每条消息的固定长度,如果消息长度小于定长的长度,则进行补位到定长长度

<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值