一节课让你学透Netty编程

Netty是一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能服务器和客户端。它是一个NIO客户机服务器框架,支持快速、简单地开发网络应用程序,如服务器和客户机。Netty大大简化了网络编程,如TCP和UDP套接字服务器。

但很多学员都向小开反应,一直在学Netty,但不得其法,学习的进度很慢。4月27日的《HelloWorld公开课》就是为了解决你的这个问题,跟着宏彪老师,一节课让你搞懂Netty。

Netty核心概念

在正式开始Netty学习前,我们先来了解几个Netty框架中的核心概念,Channel(管道),其是对Socket的封装,其包含了一组API,大大简化了直接与Socket进行操作的复杂性。

EventLoopGroup是一个EventLoop池,包含很多的EventLoop。Netty为每个Channel分配了一个EventLoop,用于处理用户连接请求、对用户请求的处理等所有事件。EventLoop本身只是一个线程驱动在其生命周期内只会绑定一个线程,让该线程处理一个Channel的所有IO事件。

ServerBootstrap用于配置整个Netty代码,将各个组件关联起来。服务端使用的是ServerBootstrap,而客户端使用的是则Bootstrap。

ChannelHandler是对Channel中数据的处理器,这些处理器可以是系统本身定义好的编

解码器,也可以是用户自定义的。这些处理器会被统一添加到一个ChannelPipeline的对象中,然后按照添加的顺序对Channel中的数据进行依次处理。

Netty中所有的I/O操作都是异步的,即操作不会立即得到返回结果,所以Netty中定义了一个ChannelFuture对象作为这个异步操作的“代言人”,表示异步操作本身。

如果想获取到该异步操作的返回值,可以通过该异步操作对象的addListener()方法为该异步操作添加监听器,为其注册回调:当结果出来后马上调用执行。Netty的异步编程模型都是建立在Future与回调概念之上的。

Scoket编程

定义服务端启动类

public class SomeServer { public static void main(String[] args) {  // 创建一个group,用于处理客户端连接请求
  NioEventLoopGroup parentGroup = new NioEventLoopGroup();  // 创建一个group,用于处理客户端连接上server后的后续请求
  NioEventLoopGroup childGroup = new NioEventLoopGroup();  try {   // bootstrap用于初始化channel
   ServerBootstrap bootstrap = new ServerBootstrap();   // 指定要使用的两个group
   bootstrap.group(parentGroup, childGroup)   // 指定要创建的channel的类型
   .channel(NioServerSocketChannel.class)   // 指定要使用的处理器
   .childHandler(new ChannelInitializer<SocketChannel>() { // 初始化channel的方法
 @Override
 protected void initChannel(SocketChannel ch)
 throws Exception { // channel一旦创建完毕,其就会同时绑定一个pipeline
 ChannelPipeline pipeline = ch.pipeline(); // 添加编码器
 pipeline.addLast(new StringEncoder()); // 添加解码器
 pipeline.addLast(new StringDecoder()); // 添加自定义的处理器
 pipeline.addLast(new SomeServerHandler());
   }
  });   // 创建channel,绑定到指定的主机(hostName,port)
   // sync()是将异步变同步
   ChannelFuture future = bootstrap.bind(8888).sync();
   System.out.println("服务器8888已经启动。。。");   // 当channel被关闭后,会触发closeFuture()的执行,去完成一些收尾工
 作
   future.channel().closeFuture().sync();
  } catch (InterruptedException e) {
   e.printStackTrace();
  } finally {   // 将两个group进行优雅关闭
   parentGroup.shutdownGracefully();
   childGroup.shutdownGracefully();
  }
 }
}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748复制代码类型:[java]

定义服务端处理器

// 自定义服务端处理器,用于处理来自于客户端的数据public class SomeServerHandler extends ChannelInboundHandlerAdapter { // 一种回调方法:当client将数据写入到channel并发送到server后,server端就会触发该方法的执行

 /**
  *
  * @param ctx 其代表当前处理器(其实它是当前处理器所封装的一个节点)
  * @param msg 就是client端发送来的数据
  * @throws Exception
  */
 @Override
 public void channelRead(ChannelHandlerContext ctx, Object msg)
 throws Exception {  // 输出client的地址与发送来的数据
  System.out.println(ctx.channel().remoteAddress() + ", " + msg);  // 向client发送一个随机的UUID
  ctx.channel().writeAndFlush("from server: " + UUID.randomUUID());
  TimeUnit.MILLISECONDS.sleep(500);
 } // 一旦在服务端发生异常,就会触发该方法的执行
 @Override
 public void exceptionCaught(ChannelHandlerContext ctx, Throwable
 cause) throws Exception {
  cause.printStackTrace();  // 关闭channel
  ctx.close();
 }
}12345678910111213141516171819202122232425262728293031复制代码类型:[java]

Netty实现HTTP请求处理

首先定义服务器启动类,该服务器用于创建并初始化服务器启动对象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]

讲师介绍

宏彪老师,原百度好看架构师,现沪智科技技术合伙人

《Hello,World公开课》是由开课吧推出的面向广大开发工程师的免费加餐课,集结业内名师大咖,聚焦热门技术和实战解决方案,以专业知识分享交流为桥梁,链接正在创造世界的一群科技主力们,向初心致敬,为技术发烧。无论你是初入职场的应届生,还是准备升职加薪的职场精英,相信这里都有你需要的养料。

(0)

相关推荐