1. 程式人生 > >對於netty中的server和cilent的編寫(初級)

對於netty中的server和cilent的編寫(初級)

在工作中遇到了使用netty編寫轉發資料的小程式,因為是第一次接觸到netty所以 將寫的心得記錄如下:

客戶端要連線到服務端,服務端需要有一個埠能夠讓客戶端去繫結 方法bind,所以服務端會佔用一個埠。

客戶端去訪問服務端的埠,需要有一個連線的方法,connect ,需要去訪問ip和port。但本身不會去佔用埠。

1.netty客戶端程式碼:

public class Client {
    public static void main(String[] args) throws Exception {
        String host = args[0];
        int port = Integer.parseInt(args[1]);
        EventLoopGroup workerGroup = new NioEventLoopGroup(); // (1)
        
        try {
            Bootstrap b = new Bootstrap(); // (2)
            b.group(workerGroup); // (3)
            b.channel(NioSocketChannel.class); // (4)
            b.option(ChannelOption.SO_KEEPALIVE, true); // (5)
            b.handler(new ChannelInitializer<SocketChannel>() { // (6)
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new ClientHandler());
                }
            });
            
            // Start the client.
            ChannelFuture f = b.connect(host, port).sync(); // (7)

            // Wait until the connection is closed.
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
        }
    }
}

客戶端的開發步驟:

(1)、 初始化用於連線及I/O工作的"執行緒池";
(2)、 初始化Bootstrap例項, 此例項是netty客戶端應用開發的入口,也是本篇介紹的重點, 下面我們會深入分析;
(3)、 通過Bootstrap的group方法,設定(1)中初始化的"執行緒池";
(4)、 指定通道channel的型別,由於是客戶端,故而是NioSocketChannel;
(5)、 設定SocketChannel的選項(此處不詳述,後面的系列會進行深入分析);
(6)、 設定SocketChannel的處理器
(7)、 連線指定的服務地址;

ClienHandler類

和server的Handler類差不多 可以參考ServerHandler

2.netty服務端程式碼:

 建立的方法:

EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
    ServerBootstrap b = new ServerBootstrap(); // (2)
    b.group(bossGroup, workerGroup)  // (3)
     .channel(NioServerSocketChannel.class) // (4)
     .handler(new LoggingHandler())    // (5)
     .childHandler(new ChannelInitializer<SocketChannel>() { // (6)
         @Override
         public void initChannel(SocketChannel ch) throws Exception {
             ch.pipeline().addLast( new ChildChannelHandler());
         }
     })
     .option(ChannelOption.SO_BACKLOG, 128)          // (7)
     .childOption(ChannelOption.SO_KEEPALIVE, true); // (8)
    
     // Bind and start to accept incoming connections.
     ChannelFuture f = b.bind(port).sync(); // (9)
    
     // Wait until the server socket is closed.
     // In this example, this does not happen, but you can do that to gracefully
     // shut down your server.
     f.channel().closeFuture().sync();
} finally {
    workerGroup.shutdownGracefully();
    bossGroup.shutdownGracefully();
}

上面這段程式碼展示了服務端的一個基本步驟:

(1)、 初始化用於Acceptor的主"執行緒池"以及用於I/O工作的從"執行緒池"

(可以參考:https://my.oschina.net/u/438393/blog/845300

(2)、 初始化ServerBootstrap例項, 此例項是netty服務端應用開發的入口
(3)、 通過ServerBootstrap的group方法,設定(1)中初始化的主從"執行緒池";
(4)、 指定通道channel的型別,由於是服務端,故而是NioServerSocketChannel;
(5)、 設定ServerSocketChannel的處理器(此處不詳述,後面的系列會進行深入分析)
(6)、 設定子通道也就是SocketChannel的處理器, 其內部是實際業務開發的"主戰場"(此處不詳述,後面的系列會進行深入分析)
(7)、 配置ServerSocketChannel的選項
(8)、 配置子通道也就是SocketChannel的選項
(9)、 繫結並偵聽某個埠

handler類:

@ChannelHandler.Sharable   //讓當前服務能夠被多個channel 共享
public class ChildChannelHandler extends ChannelInboundHandlerAdapter {  //繼承adatper類


                        //channelread方法
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
             
        //原始資料 獲取日誌
        try {
            byte[] byteMessage = (byte[]) msg;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("操作出錯:" + e);
        }
    }

服務端在初始化的時候回去new這個類 ,當服務連通後 client向伺服器傳送資料會在channelread方法裡面去讀取到。

當然還有其他關於channel 的方法  是針對於channel進行操作的時候使用的。

 

可以參考一下:https://www.cnblogs.com/itdriver/p/8149913.html