Netty學習之伺服器端建立

來源:互聯網
上載者:User

標籤:

一、伺服器端開發時序圖

  

  圖片來源:Netty權威指南(第2版)

二、Netty伺服器端開發步驟

  使用Netty進行伺服器端開發主要有以下幾個步驟:

  1、建立ServerBootstrap執行個體
ServerBootstrap b=new ServerBootstrap();

  ServerBootstrap是Netty伺服器端的啟動輔助類,提供了一系列的方法用於設定伺服器端啟動相關的參數。

  2、設定並綁定Reactor線程池
EventLoopGroup bossGruop=new NioEventLoopGroup();//用於伺服器端接受用戶端的串連EventLoopGroup workGroup=new NioEventLoopGroup();//用於網路事件的處理

  Netty的線程池是EventLoopGroup,它實際上是EventLoop的數組,EventLoop職責是處理所有註冊到本線程多工器Selector上的Channel,Selector的輪詢操作是由綁定的EventLoop線程run方法驅動。

  3、設定並綁定伺服器端Channel
b.group(bossGruop, workGroup).channel(NioServerSocketChannel.class)

  Netty對原生的NIO類庫進行封裝,作為NIO服務端,需要建立ServerSocketChannel,對應的實現是NioServerSocketChannel。

  4、鏈路建立的時候建立並初始化ChannelPipeline
b.group(bossGruop, workGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>()

  ChannelPipeline的本質是一個負責處理網路事件的職責鏈,負責管理和執行ChannelHandler。網路事件以事件流的形式在ChannelPipeline中流轉,由ChannelPipeline根據Channel|Handler的執行策略調度ChannelHandler的執行。典型的網路事件有:

  • 鏈路註冊
  • 鏈路啟用
  • 鏈路斷開
  • 接收到請求資訊
  • 請求資訊接收並處理完畢
  • 發送應答訊息
  • 鏈路發生異常
  • 使用者自訂事件
  5、添加並設定ChannelHandler
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認證

  6、綁定並啟動監聽視窗
ChannelFuture f=b.bind(port).sync();

  經過一系列初始化和檢測工作後,會啟動監聽連接埠,並將ServerSocketChannel註冊到Selector上監聽用戶端串連

  7、Selector輪詢

  由Reactor線程NioEventLoop負責調度和執行Selector輪詢操作,選擇準備就緒的Channel集合

  8、當輪詢到準備就緒的Channel之後,就由Reactor線程NioEventLoop執行ChannelPipeline的相應方法,最終調度並執行ChannelHandler
public class HelloServerHandler extends ChannelHandlerAdapter
三、Netty伺服器開發範例程式碼

   需求:伺服器端實現,每串連一個用戶端,在伺服器控制台列印用戶端輸入的字元。(註:本代碼使用的netty是netty-all-5.0.0.Alpha1-sources.jar版本)

  伺服器端代碼如下:

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;//自訂的ChannelHandlerpublic 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

  

四、參考資料

  1、Netty權威指南(李林峰)

 

Netty學習之伺服器端建立

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.