电竞比分网-中国电竞赛事及体育赛事平台

分享

一節(jié)課讓你學透Netty編程

 碼農9527 2021-04-29

 Netty是一個異步事件驅動的網絡應用程序框架,用于快速開發(fā)可維護的高性能服務器和客戶端。它是一個NIO客戶機服務器框架,支持快速、簡單地開發(fā)網絡應用程序,如服務器和客戶機。Netty大大簡化了網絡編程,如TCP和UDP套接字服務器。

    但很多學員都向小開反應,一直在學Netty,但不得其法,學習的進度很慢。4月27日的《HelloWorld公開課》就是為了解決你的這個問題,跟著宏彪老師,一節(jié)課讓你搞懂Netty。

    Netty核心概念

    在正式開始Netty學習前,我們先來了解幾個Netty框架中的核心概念,Channel(管道),其是對Socket的封裝,其包含了一組API,大大簡化了直接與Socket進行操作的復雜性。

    EventLoopGroup是一個EventLoop池,包含很多的EventLoop。Netty為每個Channel分配了一個EventLoop,用于處理用戶連接請求、對用戶請求的處理等所有事件。EventLoop本身只是一個線程驅動在其生命周期內只會綁定一個線程,讓該線程處理一個Channel的所有IO事件。

    ServerBootstrap用于配置整個Netty代碼,將各個組件關聯(lián)起來。服務端使用的是ServerBootstrap,而客戶端使用的是則Bootstrap。

    ChannelHandler是對Channel中數(shù)據(jù)的處理器,這些處理器可以是系統(tǒng)本身定義好的編

    解碼器,也可以是用戶自定義的。這些處理器會被統(tǒng)一添加到一個ChannelPipeline的對象中,然后按照添加的順序對Channel中的數(shù)據(jù)進行依次處理。

    Netty中所有的I/O操作都是異步的,即操作不會立即得到返回結果,所以Netty中定義了一個ChannelFuture對象作為這個異步操作的“代言人”,表示異步操作本身。

    如果想獲取到該異步操作的返回值,可以通過該異步操作對象的addListener()方法為該異步操作添加監(jiān)聽器,為其注冊回調:當結果出來后馬上調用執(zhí)行。Netty的異步編程模型都是建立在Future與回調概念之上的。

Java

    Scoket編程

    定義服務端啟動類

public class SomeServer { public static void main(String[] args) {  // 創(chuàng)建一個group,用于處理客戶端連接請求
  NioEventLoopGroup parentGroup = new NioEventLoopGroup();  // 創(chuàng)建一個group,用于處理客戶端連接上server后的后續(xù)請求
  NioEventLoopGroup childGroup = new NioEventLoopGroup();  try {   // bootstrap用于初始化channel
   ServerBootstrap bootstrap = new ServerBootstrap();   // 指定要使用的兩個group
   bootstrap.group(parentGroup, childGroup)   // 指定要創(chuàng)建的channel的類型
   .channel(NioServerSocketChannel.class)   // 指定要使用的處理器
   .childHandler(new ChannelInitializer<SocketChannel>() { // 初始化channel的方法
 @Override
 protected void initChannel(SocketChannel ch)
 throws Exception { // channel一旦創(chuàng)建完畢,其就會同時綁定一個pipeline
 ChannelPipeline pipeline = ch.pipeline(); // 添加編碼器
 pipeline.addLast(new StringEncoder()); // 添加解碼器
 pipeline.addLast(new StringDecoder()); // 添加自定義的處理器
 pipeline.addLast(new SomeServerHandler());
   }
  });   // 創(chuàng)建channel,綁定到指定的主機(hostName,port)
   // sync()是將異步變同步
   ChannelFuture future = bootstrap.bind(8888).sync();
   System.out.println("服務器8888已經啟動。。。");   // 當channel被關閉后,會觸發(fā)closeFuture()的執(zhí)行,去完成一些收尾工
 作
   future.channel().closeFuture().sync();
  } catch (InterruptedException e) {
   e.printStackTrace();
  } finally {   // 將兩個group進行優(yōu)雅關閉
   parentGroup.shutdownGracefully();
   childGroup.shutdownGracefully();
  }
 }
}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748復制代碼類型:[java]

    定義服務端處理器

// 自定義服務端處理器,用于處理來自于客戶端的數(shù)據(jù)public class SomeServerHandler extends ChannelInboundHandlerAdapter { // 一種回調方法:當client將數(shù)據(jù)寫入到channel并發(fā)送到server后,server端就會觸發(fā)該方法的執(zhí)行

 /**
  *
  * @param ctx 其代表當前處理器(其實它是當前處理器所封裝的一個節(jié)點)
  * @param msg 就是client端發(fā)送來的數(shù)據(jù)
  * @throws Exception
  */
 @Override
 public void channelRead(ChannelHandlerContext ctx, Object msg) 
 throws Exception {  // 輸出client的地址與發(fā)送來的數(shù)據(jù)
  System.out.println(ctx.channel().remoteAddress() + ", " + msg);  // 向client發(fā)送一個隨機的UUID
  ctx.channel().writeAndFlush("from server: " + UUID.randomUUID());
  TimeUnit.MILLISECONDS.sleep(500);
 } // 一旦在服務端發(fā)生異常,就會觸發(fā)該方法的執(zhí)行
 @Override
 public void exceptionCaught(ChannelHandlerContext ctx, Throwable 
 cause) throws Exception {
  cause.printStackTrace();  // 關閉channel
  ctx.close();
 }
}12345678910111213141516171819202122232425262728293031復制代碼類型:[java]

    Netty實現(xiàn)HTTP請求處理

    首先定義服務器啟動類,該服務器用于創(chuàng)建并初始化服務器啟動對象ServerBootStrap。

public class HttpServer { public static void main(String[] args)
    throws InterruptedException {
  EventLoopGroup parentGroup = new NioEventLoopGroup();
  EventLoopGroup childGroup = new NioEventLoopGroup();  try {
   ServerBootstrap bootstrap = new ServerBootstrap();

   bootstrap.group(parentGroup, childGroup)
  .channel(NioServerSocketChannel.class)
  .childHandler(new HttpChannelInitializer());

   ChannelFuture future = bootstrap.bind(8888).sync();
   System.out.println("服務器啟動了,端口號8888");
   future.channel().closeFuture().sync();

  } finally {
   parentGroup.shutdownGracefully();
   childGroup.shutdownGracefully();
  }
 }
}1234567891011121314151617181920212223復制代碼類型:[java]

    定義管道初始化器

public class HttpChannelInitializer
 extends ChannelInitializer<SocketChannel> { @Override
 protected void initChannel(SocketChannel ch) throws Exception {
  ChannelPipeline pipeline = ch.pipeline();
  pipeline.addLast(new HttpServerCodec());
  pipeline.addLast(new HttpServerHandler());
 }
}123456789復制代碼類型:[java]

   

    講師介紹

    宏彪老師,原百度好看架構師,現(xiàn)滬智科技技術合伙人

    《Hello,World公開課》是由開課吧推出的面向廣大開發(fā)工程師的免費加餐課,集結業(yè)內名師大咖,聚焦熱門技術和實戰(zhàn)解決方案,以專業(yè)知識分享交流為橋梁,鏈接正在創(chuàng)造世界的一群科技主力們,向初心致敬,為技術發(fā)燒。無論你是初入職場的應屆生,還是準備升職加薪的職場精英,相信這里都有你需要的養(yǎng)料。

    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多