Netty笔记3----解决粘包

Netty笔记3----解决粘包

  • 客户端启动类

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
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 TimeClient {

    public void connect(int port, String host) throws Exception {
   // 配置客户端NIO线程组
   EventLoopGroup group = new NioEventLoopGroup();
   try {
       Bootstrap b = new Bootstrap();
       b.group(group).channel(NioSocketChannel.class)
          .option(ChannelOption.TCP_NODELAY, true)
          .handler(new ChannelInitializer<SocketChannel>() {
         @Override
         public void initChannel(SocketChannel ch)
            throws Exception {
            /**
             * 加入这两行,解决粘包问题
             */
             ch.pipeline().addLast(
                new LineBasedFrameDecoder(1024));
             ch.pipeline().addLast(new StringDecoder());
             ch.pipeline().addLast(new TimeClientHandler());
         }
          });

       // 发起异步连接操作
       ChannelFuture f = b.connect(host, port).sync();

       // 当代客户端链路关闭
       f.channel().closeFuture().sync();
   } finally {
       // 优雅退出,释放NIO线程组
       group.shutdownGracefully();
   }
    }

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
   int port = 8080;
   if (args != null && args.length > 0) {
       try {
         port = Integer.valueOf(args[0]);
       } catch (NumberFormatException e) {
         // 采用默认值
       }
   }
   new TimeClient().connect(port, "127.0.0.1");
    }
}
  • 客户端实现类

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.util.logging.Logger;


public class TimeClientHandler extends ChannelInboundHandlerAdapter {

    private static final Logger logger = Logger
            .getLogger(TimeClientHandler.class.getName());

    private int counter;

    private byte[] req;

    /**
     * Creates a client-side handler.
     */
    public TimeClientHandler() {
        req = ("QUERY TIME ORDER" + System.getProperty("line.separator"))
                .getBytes();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        ByteBuf message = null;
        for (int i = 0; i < 100; i++) {
            message = Unpooled.buffer(req.length);
            message.writeBytes(req);
            ctx.writeAndFlush(message);
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        String body = (String) msg;
        System.out.println("Now is : " + body + " ; the counter is : "
                + ++counter);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // 释放资源
        logger.warning("Unexpected exception from downstream : "
                + cause.getMessage());
        ctx.close();
    }
}
  • 服务端启动类

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
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 TimeServer {

    public void bind(int port) throws Exception {
   // 配置服务端的NIO线程组
   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<SocketChannel> {
   @Override
   protected void initChannel(SocketChannel arg0) throws Exception {
      /**
       * 加入这两行,解决粘包问题
       */
       arg0.pipeline().addLast(new LineBasedFrameDecoder(1024));
       arg0.pipeline().addLast(new StringDecoder());
       arg0.pipeline().addLast(new TimeServerHandler());
   }
    }

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
   int port = 8080;
   if (args != null && args.length > 0) {
       try {
      port = Integer.valueOf(args[0]);
       } catch (NumberFormatException e) {
      // 采用默认值
       }
   }
   new TimeServer().bind(port);
    }
}
  • 服务端实现类

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class TimeServerHandler extends ChannelInboundHandlerAdapter {

    private int counter;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        String body = (String) msg;
        System.out.println("The time server receive order : " + body
                + " ; the counter is : " + ++counter);
        String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new java.util.Date(
                System.currentTimeMillis()).toString() : "BAD ORDER";
        currentTime = currentTime + System.getProperty("line.separator");
        ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
        ctx.writeAndFlush(resp);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值