其他分享
首页 > 其他分享> > Netty系列(5)Netty中解决TCP粘包和拆包

Netty系列(5)Netty中解决TCP粘包和拆包

作者:互联网

文章目录

1 TCP 粘包和拆包介绍

在这里插入图片描述

​ 假设客户端分别发送了两个数据包 D1D2 给服务端,由于服务端一次读取到字节数是不确定的,故可能存在以下四种情况:

  1. 服务端分两次读取到了两个独立的数据包,分别是 D1D2,没有粘包和拆包
  2. 服务端一次接受到了两个数据包,D1D2 粘合在一起,称之为 TCP 粘包
  3. 服务端分两次读取到了数据包,第一次读取到了完整的 D1 包和 D2 包的部分内容,第二次读取到了 D2 包的剩余内容,这称之为 TCP 拆包
  4. 服务端分两次读取到了数据包,第一次读取到了 D1 包的部分内容 D1_1,第二次读取到了 D1 包的剩余部分内容 D1_2 和完整的 D2 包,这称之为 TCP 拆包。

2 Netty 粘包演示

package com.warybee.tcp;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.nio.charset.Charset;

/**
 * @author joy
 * @create 2021-10-27 14:50
 * @description
 */
public class MyClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

    private int count;
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
        byte[] buffer = new byte[msg.readableBytes()];
        msg.readBytes(buffer);

        String message = new String(buffer, Charset.forName("utf-8"));
        System.out.println("客户端接收到消息=" + message);
        System.out.println("客户端接收消息数量=" + (++this.count));
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        for (int i = 0; i < 20; ++i) {
            ByteBuf buffer = Unpooled.copiedBuffer("你好服务端:" + i+"rn", Charset.forName("utf-8"));
            ctx.writeAndFlush(buffer);
        }
    }
}

客户端 handler 主要逻辑是:循环20次给服务端发送测试消息。接收服务端的确认消息

启动项目之后服务端收到的消息结果:

在这里插入图片描述

这里能看到多条消息被粘到一起发送了。

3 Netty中解决TCP粘包和拆包

使用自定义协议+编解码器来解决。关键就是要解决服务器端每次读取数据长度的问题,这个问题解决,就不会出现服务器多读或少读数据的问题,从而避免的 TCP 粘包、拆包。

服务端的 handler 主要逻辑是接收客户端发送过来的数据,看看是否是一条一条接收。然后每次接收到数据之后给客户端回复一个确认消息。**

标签:Netty,netty,TCP,粘包,io,new,import,public,channel
来源: https://blog.csdn.net/warybee/article/details/120995927