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