Netty學習 HelloWorld

Netty學習 HelloWorld

1.Netty簡介

Netty是一個高性能、異步事件驅動的NIO框架,它提供了對TCP、UDP和文件傳輸的支持,作爲一個異步NIO框架,Netty的所有IO操作都是異步非阻塞的,通過Future-Listener機制,用戶可以方便的主動獲取或者通過通知機制獲得IO操作結果。

作爲當前最流行的NIO框架,Netty在互聯網領域、大數據分佈式計算領域、遊戲行業、通信行業等獲得了廣泛的應用,一些業界著名的開源組件也基於Netty的NIO框架構建。

2 Netty 核心組件

2.1 Bootstrap 和 ServerBootstrap

Netty 應用程序通過設置 bootstrap(引導)類的開始,該類提供了一個 用於應用程序網絡層配置的容器。

2.2Channel

底層網絡傳輸 API 必須提供給應用 I/O操作的接口,如讀,寫,連接,綁定等等。對於我們來說,這是結構幾乎總是會成爲一個“socket”。 Netty 中的接口 Channel 定義了與 socket 豐富交互的操作集:bind, close, config, connect, isActive, isOpen, isWritable, read, write 等等。 Netty 提供大量的 Channel 實現來專門使用。這些包括 AbstractChannel,AbstractNioByteChannel,AbstractNioChannel,EmbeddedChannel, LocalServerChannel,NioSocketChannel 等等。

2.3 ChannelHandler

ChannelHandler 支持很多協議,並且提供用於數據處理的容器。我們已經知道 ChannelHandler 由特定事件觸發。 ChannelHandler 可專用於幾乎所有的動作,包括將一個對象轉爲字節(或相反),執行過程中拋出的異常處理。

2.4 ChannelPipeline

ChannelPipeline 提供了一個容器給 ChannelHandler 鏈並提供了一個API 用於管理沿着鏈入站和出站事件的流動。每個 Channel 都有自己的ChannelPipeline,當 Channel 創建時自動創建的。 ChannelHandler 是如何安裝在 ChannelPipeline? 主要是實現了ChannelHandler 的抽象 ChannelInitializer。ChannelInitializer子類 通過 ServerBootstrap 進行註冊。當它的方法 initChannel() 被調用時,這個對象將安裝自定義的 ChannelHandler 集到 pipeline。當這個操作完成時,ChannelInitializer 子類則 從 ChannelPipeline 自動刪除自身。

2.5 EventLoop

EventLoop 用於處理 Channel 的 I/O 操作。一個單一的 EventLoop通常會處理多個 Channel 事件。一個 EventLoopGroup 可以含有多於一個的 EventLoop 和 提供了一種迭代用於檢索清單中的下一個。

2.6 ChannelFuture

Netty 所有的 I/O 操作都是異步。因爲一個操作可能無法立即返回,我們需要有一種方法在以後確定它的結果。出於這個目的,Netty 提供了接口 ChannelFuture,它的 addListener 方法註冊了一個 ChannelFutureListener ,當操作完成時,可以被通知(不管成功與否)。

/**
 * Netty Server
 * Created by lyyz on 2018/5/25.
 */
public class Server {

    public static void main(String[] args) throws InterruptedException {
        //用於處理服務器端接收客戶端連接的
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        //進行網絡通信的(網絡讀寫的)
        EventLoopGroup workGroup = new NioEventLoopGroup();
        //創建輔助工具類,用於服務器通道的一系列配置
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        //綁定倆個線程組
        serverBootstrap.group(bossGroup,workGroup);
        //指定NIO的模式
        serverBootstrap.channel(NioServerSocketChannel.class);
        //3在這裏配置具體數據接收方法的處理
        serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {

            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                socketChannel.pipeline().addLast(new ServerHandler());
            }
        });
        // 引導類的配置信息
        serverBootstrap.option(ChannelOption.SO_BACKLOG,100);
        serverBootstrap.option(ChannelOption.SO_KEEPALIVE,true);
        //綁定端口
        ChannelFuture channelFuture = serverBootstrap.bind(8765).sync();

        //阻塞主線程 等等關閉
        channelFuture.channel().closeFuture().sync();

        bossGroup.shutdownGracefully();
        workGroup.shutdownGracefully();
    }
}
/**
 * Netty ServerHandler
 * 繼承 ChannelInboundHandlerAdapter 設計模式 類適配器模式
 * Created by lyyz on 2018/5/25.
 */
public class ServerHandler extends ChannelHandlerAdapter{
    /**
     * 如果有寫入方法,Netty 會自動是否ByteBuf
    * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf)msg;
        byte[] request = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(request);
        System.out.println(new String(request));
        ChannelFuture channelFuture = ctx.writeAndFlush(Unpooled.copiedBuffer("hello client".getBytes("utf-8")));
        channelFuture.addListener(ChannelFutureListener.CLOSE);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
/**
 * Netty Client
 * Created by lyyz on 2018/5/25.
 */
public class Client {
    public static void main(String[] args) throws InterruptedException, UnsupportedEncodingException {
        // 客戶端線程組 用於通訊
        EventLoopGroup workGroup = new NioEventLoopGroup();
        //客戶端的Bootstrap 引導類
        Bootstrap bootstrap = new Bootstrap();
        // 綁定線程組
        bootstrap.group(workGroup);
        //設置通道類型
        bootstrap.channel(NioSocketChannel.class);
        //添加處理類
        bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                socketChannel.pipeline().addLast(new ClientHandler());
            }
        });
        //設置客戶端引導類 參數
        bootstrap.option(ChannelOption.SO_KEEPALIVE,true);
        // 客戶端連接服務器
        ChannelFuture channelFuture = bootstrap.connect("127.0.0.1",8765).sync();
        // 通過ChannelFuture 得到管道 向管道內寫入數據
        channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer("hello server".getBytes("utf-8")));

        channelFuture.channel().closeFuture().sync();

        workGroup.shutdownGracefully();
    }
}
/**
 * Netty ClientHandler
 * 繼承 ChannelInboundHandlerAdapter 設計模式 類適配器模式
 * Created by lyyz on 2018/5/25.
 */
public class ClientHandler extends ChannelHandlerAdapter{
    /**
     * 需要手動釋放ByteBuf
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            ByteBuf byteBuf = (ByteBuf)msg;
            byte[] response = new byte[byteBuf.readableBytes()];
            byteBuf.readBytes(response);
            System.out.println(new String(response));
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章