Netty 是一個基於NIO的客戶、服務器端編程框架,使用Netty 可以確保你快速和簡單的開發出一個網絡應用,例如實現了某種協議的客戶,服務端應用。Netty相當簡化和流線化了網絡應用的編程開發過程,例如,TCP和UDP的socket服務開發。
Netty簡單來說就是socket通訊,支持多協議的通訊
對 創建 netty 的過程作了詳細的解析
1、簡單創建一個Netty服務器
package com.netty.test; import java.net.InetAddress; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; 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.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.Delimiters; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; /** * Netty4 服務端代碼 * */ public class HelloWorldServer { public static void main(String[] args) { // EventLoop 代替原來的 ChannelFactory EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try {
ServerBootstrap serverBootstrap = new ServerBootstrap(); //創建 一個netty 服務器 // server端采用簡潔的連寫方式,client端才用分段普通寫法。 serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // 指定channel[通道]類型 .childHandler(new ChannelInitializer<SocketChannel>() { // 指定Handler [操縱者]
@Override public void initChannel(SocketChannel ch) throws Exception { // 以("\n")為結尾分割的 解碼器 ch.pipeline().addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); // 字符串 解碼 和 編碼 默認的 StringDecoder 字符串形式輸出 ch.pipeline().addLast("decoder", new StringDecoder()); ch.pipeline().addLast("encoder", new StringEncoder()); ch.pipeline().addLast(new HelloServerHandler()); // 添加自己的對 上傳數據的處理 }
}).option(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = serverBootstrap.bind(8000).sync(); // 綁定 8000 端口 f.channel().closeFuture().sync(); } catch (InterruptedException e) { } finally { workerGroup.shutdownGracefully(); // 銷毀 netty bossGroup.shutdownGracefully(); } } /** * 自己對 處理數據 * * @author flm * 2017年11月10日 */ private static class HelloServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // 收到消息直接打印輸出 System.out.println(ctx.channel().remoteAddress() + " Say : " + msg); // 返回客戶端消息 - 我已經接收到了你的消息 ctx.writeAndFlush("server Received your message !\n"); } /* * * 覆蓋 channelActive 方法 在channel被啟用的時候觸發 (在建立連接的時候) * * channelActive 和 channelInActive 在后面的內容中講述,這里先不做詳細的描述 */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("RamoteAddress : " + ctx.channel().remoteAddress() + " active !"); ctx.writeAndFlush("Welcome to " + InetAddress.getLocalHost().getHostName() + " service!\n"); //回復 super.channelActive(ctx); } }
2、netty 客戶端 創建
package com.netty.test; import java.net.InetSocketAddress; import java.util.Date; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.Delimiters; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; /** * Netty4 客戶端代碼 * */ public class HelloWorldClient { public static void main(String args[]) { // Bootstrap,且構造函數變化很大,這里用無參構造。 Bootstrap bootstrap = new Bootstrap(); // 指定channel[通道]類型 bootstrap.channel(NioSocketChannel.class); // 指定Handler [操縱者] bootstrap.handler(new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); /* * 這個地方的 必須和服務端對應上。否則無法正常解碼和編碼 * */ pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); // 客戶端的邏輯,自己對數據處理 pipeline.addLast(new HelloClientHandler()); } }); // 指定EventLoopGroup [事件 組] bootstrap.group(new NioEventLoopGroup()); // 連接到本地的8000端口的服務端 bootstrap.connect(new InetSocketAddress("127.0.0.1", 8000)); } /** * 客戶端的邏輯,自己對數據處理 * * @author flm * 2017年11月10日 */ private static class HelloClientHandler extends ChannelInboundHandlerAdapter { /* * 監聽 服務器 發送來的數據 */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("Server say : " + msg.toString()); } /* * 啟動客戶端 時觸發 */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client active "); ctx.writeAndFlush("我是 client " + new Date() + "\n"); super.channelActive(ctx); } /* * 關閉 客戶端 觸發 */ @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client close "); super.channelInactive(ctx); } } }