對於netty中的server和cilent的編寫(初級)
阿新 • • 發佈:2018-12-26
在工作中遇到了使用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進行操作的時候使用的。