Netty學習:搭建一個簡單的Netty服務(JAVA NIO 類庫的非同步通訊框架)
阿新 • • 發佈:2018-12-26
http://wosyingjun.iteye.com/blog/2303296
Netty學習:搭建一個簡單的Netty服務
Netty 是一個基於 JAVA NIO 類庫的非同步通訊框架,它的架構特點是:非同步非阻塞、基於事件驅動、高效能、高可靠性和高可定製性。換句話說,Netty是一個NIO框架,使用它可以簡單快速地開發網路應用程式,比如客戶端和服務端的協議。Netty大大簡化了網路程式的開發過程比如TCP和UDP的 Socket的開發。Netty 已逐漸成為 Java NIO 程式設計的首選框架。
一. Netty 的優點:
- API 使用簡單,開發門檻低;
- 功能強大,預置了多種編解碼功能,支援多種主流協議;
- 定製能力強,可以通過 ChannelHandler 對通訊框架進行靈活的擴充套件;
- 效能高,通過與其它業界主流的 NIO 框架對比,Netty 的綜合性能最優;
- 社群活躍,版本迭代週期短,發現的 BUG 可以被及時修復,同時,更多的新功能會被加入;
- 經歷了大規模的商業應用考驗,質量得到驗證。在網際網路、大資料、網路遊戲、企業應用、電信軟體等眾多行業得到成功商用,證明了它完全滿足不同行業的商用標準。
二. 搭建Netty服務:
- 新增pom依賴
Pom程式碼- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty-all</artifactId>
- <version>4.1.0.Final</version>
- </dependency>
- SimpleServer(服務端)
Java程式碼- package com.yingjun.netty.server;
- 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;
- /**
- *
- * Netty中,通訊的雙方建立連線後,會把資料按照ByteBuf的方式進行傳輸,
- * 例如http協議中,就是通過HttpRequestDecoder對ByteBuf資料流進行處理,轉換成http的物件。
- *
- */
- publicclass SimpleServer {
- privateint port;
- public SimpleServer(int port) {
- this.port = port;
- }
- publicvoid run() throws Exception {
- //EventLoopGroup是用來處理IO操作的多執行緒事件迴圈器
- //bossGroup 用來接收進來的連線
- EventLoopGroup bossGroup = new NioEventLoopGroup();
- //workerGroup 用來處理已經被接收的連線
- EventLoopGroup workerGroup = new NioEventLoopGroup();
- try {
- //啟動 NIO 服務的輔助啟動類
- ServerBootstrap b = new ServerBootstrap();
- b.group(bossGroup, workerGroup)
- //配置 Channel
- .channel(NioServerSocketChannel.class)
- .childHandler(new ChannelInitializer<SocketChannel>() {
- @Override
- publicvoid initChannel(SocketChannel ch) throws Exception {
- // 註冊handler
- ch.pipeline().addLast(new SimpleServerHandler());
- }
- })
- .option(ChannelOption.SO_BACKLOG, 128)
- .childOption(ChannelOption.SO_KEEPALIVE, true);
- // 繫結埠,開始接收進來的連線
- ChannelFuture f = b.bind(port).sync();
- // 等待伺服器 socket 關閉 。
- f.channel().closeFuture().sync();
- } finally {
- workerGroup.shutdownGracefully();
- bossGroup.shutdownGracefully();
- }
- }
- publicstaticvoid main(String[] args) throws Exception {
- new SimpleServer(9999).run();
- }
- }
- SimpleServerHandler(服務端請求處理Handler)
Java程式碼- package com.yingjun.netty.server;
- import io.netty.buffer.ByteBuf;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.ChannelInboundHandlerAdapter;
- publicclass SimpleServerHandler extends ChannelInboundHandlerAdapter {
- @Override
- publicvoid channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- System.out.println("SimpleServerHandler.channelRead");
- ByteBuf result = (ByteBuf) msg;
- byte[] result1 = newbyte[result.readableBytes()];
- // msg中儲存的是ByteBuf型別的資料,把資料讀取到byte[]中
- result.readBytes(result1);
- String resultStr = new String(result1);
- // 接收並列印客戶端的資訊
- System.out.println("Client said:" + resultStr);
- // 釋放資源,這行很關鍵
- result.release();
- // 向客戶端傳送訊息
- String response = "hello client!";
- // 在當前場景下,傳送的資料必須轉換成ByteBuf陣列
- ByteBuf encoded = ctx.alloc().buffer(4 * response.length());
- encoded.writeBytes(response.getBytes());
- ctx.write(encoded);
- ctx.flush();
- }
- @Override
- publicvoid exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- // 當出現異常就關閉連線
- cause.printStackTrace();
- ctx.close();
- }
- @Override
- publicvoid channelReadComplete(ChannelHandlerContext ctx) throws Exception {
- ctx.flush();
- }
- }
- SimpleServer(客戶端)
Java程式碼- package com.yingjun.netty.server;
- import io.netty.bootstrap.Bootstrap;
- 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.channel.socket.nio.NioSocketChannel;
- publicclass SimpleClient {
- publicvoid connect(String host, int port) throws Exception {
- EventLoopGroup workerGroup = new NioEventLoopGroup();
- try {
- Bootstrap b = new Bootstrap();
- b.group(workerGroup);
- b.channel(NioSocketChannel.class);
- b.option(ChannelOption.SO_KEEPALIVE, true);
- b.handler(new ChannelInitializer<SocketChannel>() {
- @Override
- publicvoid initChannel(SocketChannel ch) throws Exception {
- ch.pipeline().addLast(new SimpleClientHandler());
- }
- });
- // Start the client.
- ChannelFuture f = b.connect(host, port).sync();
- // Wait until the connection is closed.
- f.channel().closeFuture().sync();
- } finally {
- workerGroup.shutdownGracefully();
- }
- }
- publicstaticvoid main(String[] args) throws Exception {
- SimpleClient client=new SimpleClient();
- client.connect("127.0.0.1", 9999);
- }
- }
- SimpleServerHandler(客戶端請求處理Handler)
Java程式碼- package com.yingjun.netty.server;
- import io.netty.buffer.ByteBuf;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.ChannelInboundHandlerAdapter;
- publicclass SimpleClientHandler extends ChannelInboundHandlerAdapter {
- @Override
- publicvoid channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- System.out.println("SimpleClientHandler.channelRead");
- ByteBuf result = (ByteBuf) msg;
- byte[] result1 = newbyte[result.readableBytes()];
- result.readBytes(result1);
- System.out.println("Server said:" + new String(result1));
- result.release();
- }
- @Override
- publicvoid exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- // 當出現異常就關閉連線
- cause.printStackTrace();
- ctx.close();
- }
- // 連線成功後,向server傳送訊息
- @Override
- publicvoid channelActive(ChannelHandlerContext ctx) throws Exception {
- String msg = "hello Server!";
- ByteBuf encoded = ctx.alloc().buffer(4 * msg.length());
- encoded.writeBytes(msg.getBytes());
- ctx.write(encoded);
- ctx.flush();
- }
- }
- 執行結果:
Java程式碼- SimpleClientHandler.channelRead
- Server said:hello client!
- ------------------------------------------
- SimpleServerHandler.channelRead
- Client said:hello Server!
- SimpleServerHandler.channelRead
- Client said:hello Server!