圖片來源:Netty權威指南(第2版)bootstrap
使用Netty進行服務器端開發主要有如下幾個步驟:數組
ServerBootstrap b=new ServerBootstrap();
ServerBootstrap是Netty服務器端的啓動輔助類,提供了一系列的方法用於設置服務器端啓動相關的參數。安全
EventLoopGroup bossGruop=new NioEventLoopGroup();//用於服務器端接受客戶端的鏈接 EventLoopGroup workGroup=new NioEventLoopGroup();//用於網絡事件的處理
Netty的線程池是EventLoopGroup,它其實是EventLoop的數組,EventLoop職責是處理全部註冊到本線程多路複用器Selector上的Channel,Selector的輪詢操做是由綁定的EventLoop線程run方法驅動。服務器
b.group(bossGruop, workGroup).channel(NioServerSocketChannel.class)
Netty對原生的NIO類庫進行封裝,做爲NIO服務端,須要建立ServerSocketChannel,對應的實現是NioServerSocketChannel。網絡
b.group(bossGruop, workGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>()
ChannelPipeline的本質是一個負責處理網絡事件的職責鏈,負責管理和執行ChannelHandler。網絡事件以事件流的形式在ChannelPipeline中流轉,由ChannelPipeline根據Channel|Handler的執行策略調度ChannelHandler的執行。典型的網絡事件有:socket
b.group(bossGruop, workGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel arg0) throws Exception { arg0.pipeline().addLast(new HelloServerHandler()); } }).option(ChannelOption.SO_BACKLOG, 1024);
ChannelHandler是Netty提供給用戶定製和擴展的接口,例如消息編解碼、心跳、安全認證、TSL/SSL認證ide
ChannelFuture f=b.bind(port).sync();
通過一系列初始化和檢測工做後,會啓動監聽端口,並將ServerSocketChannel註冊到Selector上監聽客戶端鏈接oop
由Reactor線程NioEventLoop負責調度和執行Selector輪詢操做,選擇準備就緒的Channel集合this
public class HelloServerHandler extends ChannelHandlerAdapter
需求:服務器端實現,每鏈接一個客戶端,在服務器控制檯打印客戶端輸入的字符。(注:本代碼使用的netty是netty-all-5.0.0.Alpha1-sources.jar版本)url
服務器端代碼以下:
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服務器端 public class HelloServer { private int port; public HelloServer(int port) { super(); this.port = port; } private void bind() throws InterruptedException { EventLoopGroup bossGruop=new NioEventLoopGroup();//用於服務器端接受客戶端的鏈接 EventLoopGroup workGroup=new NioEventLoopGroup();//用於網絡事件的處理 try { ServerBootstrap b=new ServerBootstrap(); b.group(bossGruop, workGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel arg0) throws Exception { arg0.pipeline().addLast(new HelloServerHandler()); } }).option(ChannelOption.SO_BACKLOG, 1024);//指定此套接口排隊的最大鏈接個數 ChannelFuture f=b.bind(port).sync(); f.channel().closeFuture().sync(); } finally { bossGruop.shutdownGracefully(); workGroup.shutdownGracefully(); } } public static void main(String[] args) throws InterruptedException { new HelloServer(8080).bind(); } }
import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; //自定義的ChannelHandler public class HelloServerHandler extends ChannelHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("客戶端連上了..."); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf=(ByteBuf) msg; byte[] req=new byte[buf.readableBytes()]; buf.readBytes(req); System.out.println("服務器端接收的消息:"+new String(req)); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); } }
客戶端:使用telnet模擬客戶端輸入,
按住「ctrl+]」,而後輸入指令send a