网络通信 粘包拆包问题

粘包拆包 问题

基于tcp进行客户端和服务端通信是会存在粘包的问题,以下是基于netty构建tcp客户端服务端时的粘包问题解决方案

在 Netty 中,粘包问题是可以通过内建的解码器来解决的,比如 LengthFieldBasedFrameDecoder 或者 DelimiterBasedFrameDecoder。以下是两种解决方案:

1、使用 DelimiterBasedFrameDecoder

如果你的协议是基于分隔符的,可以使用 DelimiterBasedFrameDecoder。例如,你的协议使用换行符 \n 作为每个消息的结尾,你可以这样来配置你的 ChannelPipeline:

ByteBuf delimiter = Unpooled.copiedBuffer("\n", CharsetUtil.UTF_8);
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, delimiter));

2、使用 LengthFieldBasedFrameDecoder

如果你的协议是基于长度的,可以使用 LengthFieldBasedFrameDecoder。例如,你的协议定的消息格式为HEADER(LENGTH)+BODY,其中 HEADER 是一个固定长度的头部,存储了整个消息的长度,你可以这样来配置你的 ChannelPipeline:

pipeline.addLast(new LengthFieldBasedFrameDecoder(8192, 0, 4, 0, 4));

以上两种方式都可以解决 Netty 的粘包问题,具体使用哪种方式取决于你的协议。

注意:8192 是你预期的最大帧大小,如果你预计你的数据会有更大的帧,你需要调整这个值。‘0’ 和 ‘4’ 是长度字段的偏移量和长度字段的大小。如果你的长度字段不在消息的开始位置,你需要调整偏移量。如果你的长度字段的大小不是4,你需要调整长度字段的大小。

希望这些信息能对你有所帮助!如果你还有其他问题,欢迎随时提问。

如果你希望基于正则匹配来进行分包,可以使用 ByteToMessageDecoder,它是 DelimiterBasedFrameDecoder 的一个子类,用于根据正则匹配来进行分包。换行符通常用于标识每个数据包的结束。

使用 LineBasedFrameDecoder 的示例如下:

class MyDelimiterDecoder  extends ByteToMessageDecoder {
	// 就比如 我的每个包 以 &&1234 结尾,可以使用下述正则
    private static final String DELIMITER_REGEX = "&&\\d{4}";
    private static final Pattern DELIMITER_PATTERN = Pattern.compile(DELIMITER_REGEX);

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // 查找是否有匹配的结尾
        int delimiterIndex = indexOfDelimiter(in);
        if (delimiterIndex == -1) {
            // 没有找到结尾,等待更多数据
            return;
        }

        // 将结尾之前的数据拆分成一个新的 ByteBuf
        ByteBuf frame = in.readRetainedSlice(delimiterIndex + DELIMITER_REGEX.length()-1);

        // 添加到输出列表中
        out.add(frame);
    }

    private int indexOfDelimiter(ByteBuf buffer) {
        // 将 ByteBuf 转换成字符串
        String data = buffer.toString(CharsetUtil.UTF_8);

        // 使用正则表达式匹配结尾的位置
        Matcher matcher = DELIMITER_PATTERN.matcher(data);
        if (matcher.find()) {
            return matcher.start();
        }
        return -1;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

对你偏爱u

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值