资讯专栏INFORMATION COLUMN

使用 LineBasedFrameDecoder 和 StringDecoder 解决半包粘包问题

HollisChuang / 2343人阅读

摘要:修改之前的服务端开发代码修改为下面代码绑定端口同步等待成功等待服务端监听端口关闭主要修改了和方法和原理分析的工作原理是它依次遍历中的可读字节判断看是否有或如果有就以此位置为结束位置从可读索引到结束位置区间的字节就组成了一行它是以换行符为结束

修改之前的 Netty 服务端开发 代码, 修改为下面代码

public class TimeServer {

    public void bind(int port) throws Exception {

        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childHandler(new ChildChannelHandler());

            // 绑定端口, 同步等待成功
            ChannelFuture f = b.bind(port).sync();

            // 等待服务端监听端口关闭
            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    private class ChildChannelHandler extends ChannelInitializer {

        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            ch.pipeline().addLast(new LineBasedFrameDecoder(1024));
            ch.pipeline().addLast(new StringDecoder());
            ch.pipeline().addLast(new TimeServerHandler());
        }
    }

    private class TimeServerHandler extends ChannelHandlerAdapter {
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            ctx.close();
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            String body = (String) msg;
            System.out.println(body);

            ByteBuf resp = Unpooled.copiedBuffer("6666".getBytes());
            ctx.write(resp);
        }

        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            ctx.flush();
        }
    }

}

主要修改了 initChannelchannelRead 方法.

LineBasedFrameDecoder 和 StringDecoder 原理分析

LineBasedFrameDecoder 的工作原理是它依次遍历 ByteBuf 中的可读字节, 判断看是否有 , 如果有, 就以此位置为结束位置, 从可读索引到结束位置区间的字节就组成了一行.

它是以换行符为结束标志的解码器, 支持携带结束符或者不携带结束符两种解码方式, 同时支持配置单行的最大长度. 如果连续读取到最大长度后仍然没有发现换行符, 就会抛出异常, 同时忽略之前读到的异常码流.

StringDecoder 的功能非常简单, 就是将收到的对象转换成字符串, 然后继续调用后面Handler.

LineBasedFrameDecoder + StringDecoder 组合就是按行切换的文本解码器, 它被设计用来支持 TCP 的粘包和拆包.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72740.html

相关文章

  • 基于定长消息的java nio半包粘包处理

    摘要:接收方只需要等待,直到读到确定数量的字节,然后处理即可。而这个字节流的前个字节用于表示对象的长度,接下来的字节就是传输的对象的字节流,最后不够最大长度的用任意字节进行填充即可。 什么是tcp半包粘包?简单来讲就是接收到的tcp包并不一定是一个完整的包。它可能是1个包的一部分,也可能是多个完整包加上1个包的一部分。为什么?因为tcp的定义是面向字节流的传输协议,所以操作系统实现这个协议的...

    Loong_T 评论0 收藏0
  • Netty(三) 什么是 TCP 拆、粘包?如何解决

    摘要:是一个面向字节流的协议,它是性质是流式的,所以它并没有分段。可基于分隔符解决。编解码的主要目的就是为了可以编码成字节流用于在网络中传输持久化存储。 showImg(https://segmentfault.com/img/remote/1460000015895049); 前言 记得前段时间我们生产上的一个网关出现了故障。 这个网关逻辑非常简单,就是接收客户端的请求然后解析报文最后发送...

    YanceyOfficial 评论0 收藏0
  • 分隔符定长解码器的应用

    摘要:以流的方式进行数据传输上层的应用协议为了对消息进行区分往往采用如下中方式消息长度固定累计读取到长度总和为定长的报文后就认为读到了一个完整的消息将计数器置位重新开始读取下一个数据报将回车换行符作为消息结束符例如协议这种方式在文本协议中应用比较 TCP 以流的方式进行数据传输, 上层的应用协议为了对消息进行区分, 往往采用如下 4 中方式. 消息长度固定, 累计读取到长度总和为定长 LE...

    lemon 评论0 收藏0
  • netty

    摘要:设置每个数据包的大小如个字节,如果某个数据包不足个字节可能会出现丢包的情况,即该数据包未从一个端到另一个端,此时需要用空格或者既定的符号补充在数据包之间使用一些字符进行分割如号之类的,解析的时候先处理掉分隔符再拿到各个数据包就好了。 netty 概念: Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠...

    cfanr 评论0 收藏0
  • 彻底理解Netty,这一篇文章就够了

    摘要:如果什么事都没得做,它也不会死循环,它会将线程休眠起来,直到下一个事件来了再继续干活,这样的一个线程称之为线程。而请求处理逻辑既可以使用单独的线程池进行处理,也可以跟放在读写线程一块处理。 Netty到底是什么 从HTTP说起 有了Netty,你可以实现自己的HTTP服务器,FTP服务器,UDP服务器,RPC服务器,WebSocket服务器,Redis的Proxy服务器,MySQL的P...

    yy13818512006 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<