1. 程式人生 > 其它 >Netty 快速入門

Netty 快速入門

技術標籤:Netty學習

2.3 Netty快速入門

2.3.1 伺服器端

  • 建立了bossGroup 和 workerGroup

  • 觀察bootstrap.group(bossGroup, workerGroup)方法

    可以看出bossGroup 是 parentGroup ,workerGroup 是 childGroup

在這裡插入圖片描述

  • 給workerGroup初始化通道,然後向管道里面扔一個Handler
//建立BossGroup 和 WorkerGroup,都是無限迴圈
//子執行緒NioEventLoop的默認個數是CPU核心數*2
EventLoopGroup bossGroup = new
NioEventLoopGroup(1); //只處理連線請求 NioEventLoopGroup workerGroup = new NioEventLoopGroup(); //處理業務 try{ ServerBootstrap bootstrap = new ServerBootstrap(); //伺服器啟動物件 bootstrap.group(bossGroup, workerGroup) //兩個執行緒組 .channel(NioServerSocketChannel.class) //伺服器通道 .option(ChannelOption.
SO_BACKLOG, 128) //執行緒佇列等待連線的個數 .childOption(ChannelOption.SO_KEEPALIVE, true) //保持活動連線狀態 .childHandler(new ChannelInitializer<SocketChannel>() { //建立一個通道初始化物件 //給pipeline設定處理器 @Override protected void initChannel(SocketChannel ch)
throws Exception { ch.pipeline().addLast(new NettyServerHandler()); } }); //給workerGroup 的 EventLoop設定處理器 System.out.println("server is ready"); ChannelFuture cf = bootstrap.bind(6668).sync(); //繫結埠並且同步,就是啟動伺服器 cf.channel().closeFuture().sync(); //對關閉通道進行監聽 } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); }
  • Handler程式碼

    Handler繼承了ChannelInboundHandlerAdapter

  • 並且複寫的是生命週期函式

    • channelRead – 讀取客戶端傳送的訊息
    • channelReadComplete – 資料讀取完畢
    • exceptionCaught – 發生異常
  • 其中的ctx有很多東西

  • msg可以轉成ByteBuf,這是Netty提供的一個東西

public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    //讀取客戶端傳送的訊息
    /*
    *  ctx中有
    * 管道:Handler處理
    * 通道:資料處理
    * 地址
    * msg就是客戶端傳送的資料
    * */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // super.channelRead(ctx, msg);
        System.out.println("Server ctx = " + ctx);
        ByteBuf buf = (ByteBuf) msg;

        Channel channel = ctx.channel();

        System.out.println("客戶端傳送的訊息是:" + buf.toString(CharsetUtil.UTF_8));
        System.out.println("客戶端地址:" + channel.remoteAddress());
    }

    //資料讀取完畢
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // super.channelReadComplete(ctx);
        ctx.writeAndFlush(Unpooled.copiedBuffer("Hello,客戶端",CharsetUtil.UTF_8)); //寫入緩衝並重新整理
    }

    //發生異常
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //super.exceptionCaught(ctx, cause);
        ctx.close();
    }
}

2.3.2 伺服器端

  • 客戶端這裡設定相對較少

    其中不同的是它的操作是連線客戶端

    ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6668).sync();

//事件迴圈組
 NioEventLoopGroup eventExecutors = new NioEventLoopGroup();

try{
    //客戶端啟動物件
    Bootstrap bootstrap = new Bootstrap();

    bootstrap.group(eventExecutors) //設定執行緒組
            .channel(NioSocketChannel.class) //客戶端通道
            .handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new NettyClientHandler()); //加入Handler
                }
            });

    System.out.println("Client is Ready");

    //啟動客戶端連線伺服器端
    ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6668).sync();
    channelFuture.channel().closeFuture().sync();
} finally {
    eventExecutors.shutdownGracefully();
}
  • 來看Handler,依舊是複寫生命週期函式
public class NettyClientHandler extends ChannelInboundHandlerAdapter {

    //通道就緒
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // super.channelActive(ctx);
        System.out.println("Client " + ctx);
        ctx.writeAndFlush(Unpooled.copiedBuffer("Hello Server: 淦", CharsetUtil.UTF_8));
    }

    //通道有讀取事件時
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //super.channelRead(ctx, msg);
        ByteBuf buf = (ByteBuf)msg;
        System.out.println("伺服器傳送回覆的訊息: " + buf.toString(CharsetUtil.UTF_8));
        System.out.println("伺服器的地址:" + ctx.channel().remoteAddress());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//        super.exceptionCaught(ctx, cause);
        cause.printStackTrace();
        ctx.close();
    }
}