Netty的分隔符解码器的使用
来源:互联网 发布:淘宝购物车营销 编辑:程序博客网 时间:2024/05/17 07:22
TCP以流的方式进行数据传输,上层的应用协议为了对消息进行区分,采用消息长度固定、以回车换行符作为结束标志、特殊分隔符作为结束标志、消息头中定义长度等方式。Netty对于这几种方式做了统一的抽象,分别提供四种解码器解决。
在这里,我使用DelimiterBasedFrameDecoder解码器来解决以分隔符作为结束标志的消息的解码。
PS:FixedLengthFrameDecoder是定长消息的解码。
程序演示echo服务,服务端收到客户端的请求消息后,将其打印出来,并将原消息返回给客户端。程序以“$$”为分隔符。
服务端:
EchoServer类
public class EchoServer { public void bind(int port) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); ServerBootstrap bootstrap = new ServerBootstrap(); try { bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ByteBuf delimiter = Unpooled.copiedBuffer("$$".getBytes()); ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter)); ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new EchoServerHandler() ); } }); ChannelFuture future = bootstrap.bind(port).sync(); future.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port = 443; new EchoServer().bind(port); }}
EchoServerHandler类
public class EchoServerHandler extends ChannelInboundHandlerAdapter { private int count = 0; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String body = (String) msg; System.out.println("This is : " + ++count + " times receive client , body is " + body); body += "$$"; ByteBuf echo = Unpooled.copiedBuffer(body.getBytes()); ctx.writeAndFlush(echo); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); }}
客户端
EchoClient类
public class EchoClient { public void connect(int port, String host) throws Exception { // 配置客户端NIO 线程组 EventLoopGroup group = new NioEventLoopGroup(); Bootstrap client = new Bootstrap(); try { client.group(group).channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ByteBuf delimiter = Unpooled.copiedBuffer("$$".getBytes()); ch.pipeline().addLast( new DelimiterBasedFrameDecoder(1024, delimiter)); ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new EchoClientHandler()); } }); ChannelFuture future = client.connect(host, port).sync(); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } public static void main(String[] args) { int port = 443; EchoClient client = new EchoClient(); try { client.connect(port, "127.0.0.1"); } catch (Exception e) { e.printStackTrace(); } }}
EchoClientHandler类
public class EchoClientHandler extends ChannelInboundHandlerAdapter { private int count; static final String ECHO_REQ = "hello, welcome to Netty,$$"; @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { for (int i = 0; i < 10; i++) { ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes())); } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String body = (String) msg; System.out.println("This is : " + ++count + " times receive client , body is " + body); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); }}
运行结果,客户端和服务器都会打印如下的内容,说明使用DelimiterBasedFrameDecoder可以完成以分隔符为结束标志的解码。
This is : 1 times receive client , body is hello, welcome to Netty,This is : 2 times receive client , body is hello, welcome to Netty,This is : 3 times receive client , body is hello, welcome to Netty,This is : 4 times receive client , body is hello, welcome to Netty,This is : 5 times receive client , body is hello, welcome to Netty,This is : 6 times receive client , body is hello, welcome to Netty,This is : 7 times receive client , body is hello, welcome to Netty,This is : 8 times receive client , body is hello, welcome to Netty,This is : 9 times receive client , body is hello, welcome to Netty,This is : 10 times receive client , body is hello, welcome to Netty,
如果想测试一下没有使用分隔符的解码器,其实只需要注释掉服务端一下两条语句即可。
ByteBuf delimiter = Unpooled.copiedBuffer("$$".getBytes()); ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter));
然后服务端的结果为:
This is : 1 times receive client , body is hello, welcome to Netty,$$hello, welcome to Netty,$$hello, welcome to Netty,$$hello, welcome to Netty,$$hello, welcome to Netty,$$hello, welcome to Netty,$$hello, welcome to Netty,$$hello, welcome to Netty,$$hello, welcome to Netty,$$hello, welcome to Netty,$$
客户端的结果为:
This is : 1 times receive client , body is hello, welcome to Netty,This is : 2 times receive client , body is hello, welcome to Netty,This is : 3 times receive client , body is hello, welcome to Netty,This is : 4 times receive client , body is hello, welcome to Netty,This is : 5 times receive client , body is hello, welcome to Netty,This is : 6 times receive client , body is hello, welcome to Netty,This is : 7 times receive client , body is hello, welcome to Netty,This is : 8 times receive client , body is hello, welcome to Netty,This is : 9 times receive client , body is hello, welcome to Netty,This is : 10 times receive client , body is hello, welcome to Netty,This is : 11 times receive client , body is
根据结果可以清楚的看到,没有分隔符解码器导致服务端一次读取了客户端发的所有消息,这也是典型的没有考虑TCP粘包问题导致的。
阅读全文
1 0
- Netty的分隔符解码器的使用
- Netty (四) 分隔符和定长解码器的使用
- Netty分隔符解码器和定长解码器的应用方案
- Netty的分隔符和定长解码器应用
- Netty中分隔符和定长解码器的应用
- 《netty权威指南》5分隔符和定长解码器的应用
- [netty]--分隔符解码器DelimiterBasedFrameDecoder和定长解码器FixedLengthFrameDecoder
- Netty权威指南 第2版学习笔记5——分隔符和定长解码器的应用
- Netty权威指南之分隔符和定长解码器
- netty之分隔符和定长解码器解决之道
- 分隔符和定长解码器在netty中的应用
- 七、分隔符和定长解码器的应用(1)
- 八、分隔符和定长解码器的应用(2)
- netty分割符和定长解码器的应用
- netty:protobuf的编码器ProtobufVarint32LengthFieldPrepender()、解码器ProtobufVarint32FrameDecoder()
- <netty权威指南>笔记-分隔符解码器处理半包问题
- Netty学习之旅(三)(分隔符和定长解码器)
- Netty解决分包的几种解码器介绍
- CreateFileMapping_1
- 记念我的第一个篇博客
- P1214 等差数列
- Stack的三种含义
- jFinal位置项目绝对位置,访问地址位置,端口
- Netty的分隔符解码器的使用
- 枚举的使用
- JNI笔记 JNI开发流程
- js延时操作并传参数写法
- 不知道服务器是否存在CVE漏洞,不如用云鉴漏洞平台扫一扫
- 利用mysql事务隔离级别解决php高并发问题
- 【matlab dijkstra单源最短路径算法】dijkstra单源最短路径算法实现
- OkHttp使用完全教程
- 53、54、55