3.Netty的粘包、拆包(二)

想要了解一下的,请点击这里 Chick Here!

今天我们要讲解的是Netty提供的两种解决方案:

DelimiterBasedFrameDecoder

FixedLengthFrameDecoder

2.关于Decoder

先观察下两段代码的不同

(1)使用StringDecoder之前

@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { try { ByteBuf in = (ByteBuf) msg; String str = in.toString(CharsetUtil.UTF_8); System.out.println("Client:"+str); } finally { ReferenceCountUtil.release(msg); } }

(2)使用StringDecoder之后

@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { try { String str = (String) msg; System.out.println("Client:"+str); } finally { ReferenceCountUtil.release(msg); } }

关于Decoder

decoder:n. 解码器

在我看来,Netty数据的解析方式大概为:

发送过程:Buffer------>数据报------>比特流

接受过程:Buffer<------数据报<------比特流

所以我们接受到的msg是一个ButeBuf

使用了Decoder(这里使用StringDecoder举例)之后:

发送过程:Buffer------>数据报------>比特流

接受过程:String<------Buffer<------数据报<------比特流

相当于ByteBuf按照StringDecoder的解码规则,把msg翻译成为了一个字符串。

如何使用Decoder

(1)实际代码演示:

package com.xm.netty.demo02; import java.net.InetSocketAddress; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.string.StringDecoder; public class Server { private final int port; public Server(int port) { this.port = port; } public static void main(String[] args) { int port = 8989; try { new Server(port).start(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void start() throws InterruptedException { EventLoopGroup g1 = new NioEventLoopGroup(); EventLoopGroup g2 = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap .group(g1,g2) .channel(NioServerSocketChannel.class) .localAddress(new InetSocketAddress( port)) .childHandler(new ChannelInitializer() { @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new ServerHandler()); } }); ChannelFuture future = bootstrap.bind().sync(); future.channel().closeFuture().sync(); } finally { g1.shutdownGracefully().sync(); g2.shutdownGracefully().sync(); } } }

代码改动:

ch.pipeline().addLast(new StringDecoder());

​ ch.pipeline().addLast(new ServerHandler());

(2)多个Decoder的使用顺序:

从前往后,依次解码

假设我们有个通过字符串变化为时间的TimeDecoder:

ch.pipeline().addLast(new StringDecoder());

ch.pipeline().addLast(new TimeDecoder());

​ ch.pipeline().addLast(new ServerHandler());

解析规则为:

3.Netty的粘包、拆包(二)

3.DelimiterBasedFrameDecoder

关于DelimiterBasedFrameDecoder

其实很简单,就是在一个缓冲区的末尾添加一个结束字符。

在规定了最大长度的缓冲区里,遇到一个特殊字符,就截取一次。

原理类似于String的split()方法。

代码实现

(1)服务端Server

package com.xm.netty.demo03; import java.net.InetSocketAddress; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; public class Server { private final int port; public Server(int port) { this.port = port; } public static void main(String[] args) { int port = 8989; try { new Server(port).start(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void start() throws InterruptedException { EventLoopGroup g1 = new NioEventLoopGroup(); EventLoopGroup g2 = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap .group(g1,g2) .channel(NioServerSocketChannel.class) .localAddress(new InetSocketAddress( port)) .childHandler(new ChannelInitializer() { @Override protected void initChannel(Channel ch) throws Exception { ByteBuf buf = Unpooled.copiedBuffer("$".getBytes()); ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf)); ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new ServerHandler()); } }); ChannelFuture future = bootstrap.bind().sync(); future.channel().closeFuture().sync(); } finally { g1.shutdownGracefully().sync(); g2.shutdownGracefully().sync(); } } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfpys.html