netty(一) 利用 LineBasedFrameDecoder,StringDecoder解决TCP粘包/拆包问题
2018-08-16 10:34
323 查看
.一,TCP粘包/拆包问题图示
产生TCP粘包/拆包问题如下几点:
TCP粘包/拆包问题解决方案:
二,利用 LineBasedFrameDecoder,StringDecoder解决TCP粘包/拆包问题
server端代码示例:
[code]package nettyDemo3; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.LineBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; public class TimeServerHanler extends ChannelHandlerAdapter { private int counter; // 计数器 /** * 抛异常会调用此方法 */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // TODO Auto-generated method stub // super.exceptionCaught(ctx, cause); cause.printStackTrace(); ctx.close(); } /** * 读取客户端回应的消息 */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // TODO Auto-generated method stub // super.channelRead(ctx, msg); // ByteBuf buf = (ByteBuf) msg; // byte[] bytes = new byte[buf.readableBytes()]; // buf.readBytes(bytes); // String body = new String(bytes, "UTF-8"); // System.getProperty("line.separator") 换行符 String body = (String) msg; System.out.println(body + "【第" + (++counter) + "次收到客户端的消息】"); String result = "i am server" + System.getProperty("line.separator"); ByteBuf buf2 = Unpooled.copiedBuffer(result.getBytes()); ctx.write(buf2); } /** * 读取完成之后会调用此方法 */ @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { // TODO Auto-generated method stub // super.channelReadComplete(ctx); ctx.flush(); System.out.println("读取完成"); } public static void main(String[] args) { // 配置服务端线程组,一个负责连接 ,一个负责读写 EventLoopGroup boss = new NioEventLoopGroup(); EventLoopGroup worker = new NioEventLoopGroup(); try { // 创建服务端辅助启动类并设置参数 ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(boss, worker).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 { // TODO Auto-generated method stub // 添加回车换行符解码器 ch.pipeline().addLast(new LineBasedFrameDecoder(1024)); ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new TimeServerHanler()); } }); int inetPort = 8080; // 绑定端口,并开始阻塞等待客户端的连接 ChannelFuture f = bootstrap.bind(inetPort).sync(); f.channel().closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); } finally { // 优雅退出,释放线程池资源 boss.shutdownGracefully(); worker.shutdownGracefully(); } } }
client端代码示例:
[code]package nettyDemo3; import org.omg.PortableServer.POA; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.LineBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; public class TimeClientHandler extends ChannelHandlerAdapter { private int counter; /** * 抛异常会调用此方法 */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // TODO Auto-generated method stub // super.exceptionCaught(ctx, cause); ctx.close(); cause.printStackTrace(); } /** * 当客户端成功连接上服务端之后会调用此方法 */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // TODO Auto-generated method stub // super.channelActive(ctx); byte[] msg = ("i am clien" + System.getProperty("line.separator")).getBytes(); ByteBuf buf = null; for (int i = 0; i < 50; i++) { buf = Unpooled.buffer(msg.length); buf.writeBytes(msg); ctx.writeAndFlush(buf); } } /** * 读取服务端回应的消息 */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // TODO Auto-generated method stub // super.channelRead(ctx, msg); // ByteBuf buf = (ByteBuf) msg; // byte[] bytes = new byte[buf.readableBytes()]; // buf.readBytes(bytes); // String body = new String(bytes, "UTF-8"); String body = (String) msg; System.out.println(body + "【第" + (++counter) + "次收到服务端的消息】"); } public static void main(String[] args) { // 配置客户端端线程组负责读写 EventLoopGroup work = new NioEventLoopGroup(); try { // 创建客户端的辅助启动类并设置参数 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(work).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { // TODO Auto-generated method stub // 添加解码器 ch.pipeline().addLast(new LineBasedFrameDecoder(1024)); ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new TimeClientHandler()); } }); final String host = "127.0.0.1"; final int port = 8080; // 连接服务端 ChannelFuture future = bootstrap.connect(host, port).sync(); future.channel().closeFuture().sync(); } catch (Exception e) { // TODO: handle exception } finally { // 优雅退出,释放线程池资源 work.shutdownGracefully(); } } }
分别运行客户端和服务端实例,看到控制台输出以下图片中的内容,说明成功解决tcp粘包/拆包问题。
附: netty利用DelimiterBasedFrameDecoder 和 FixedLengthFrameDecoder 也可以按需自定义解码实现粘包/拆包问题
[code]//添加自定义以$_为分隔符的解码器 ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes()); ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf)); //添加固定长度解码器 ch.pipeline().addLast(new FixedLengthFrameDecoder(13));
阅读更多
相关文章推荐
- Netty使用LineBasedFrameDecoder解决粘包问题
- 《netty权威指南》4.3利用LineBasedFrameDecoder解决TCP粘包问题
- 利用LineBasedFrameDecoder解决TCP粘包问题
- TCP粘包/拆包--利用LineBasedFrameDecoder解决TCP粘包问题
- Netty5中使用LineBasedFrameDecoder解决TCP粘包问题
- TCP粘包/拆包--利用DelimiterBasedFrameDecoder解决TCP粘包问题
- netty5.0通过LineBasedFrameDecoder和StringDecoder解决粘包
- LineBasedFrameDecoder 行解码器,回车换行符解决 TCP 粘包
- java netty使用DelimiterBasedFrameDecoder处理tcp粘包问题
- Netty2:粘包/拆包问题与使用LineBasedFrameDecoder的解决方案
- netty——LengthFieldBasedFrameDecoder实例(解决半包)
- TCP粘包/拆包--利用FixedLengthFrameDecoder解决TCP粘包问题
- netty 拆包粘包(LineBasedFrameDecoder)
- netty 过长内容分成了多次发送 问题 LengthFieldBasedFrameDecoder使用
- 3.netty解码器LineBaseFrameDecoder、StringDecoder
- Netty学习(六)-LengthFieldBasedFrameDecoder解码器
- 一起学Netty(九)之LengthFieldBasedFrameDecoder
- NETTY源码学习-DELIMITERBASEDFRAMEDECODER
- netty入门学习(4)-LengthFieldPrepender和LengthFieldBasedFrameDecoder
- Netty LengthFieldBasedFrameDecoder