Netty系列入门之HelloWorld(一)编程
一. 简介promise
Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server.服务器
'Quick and easy' doesn't mean that a resulting application will suffer from a maintainability or a performance issue. Netty has been designed carefully with the experiences earned from the implementation of a lot of protocols such as FTP, SMTP, HTTP, and various binary and text-based legacy protocols. As a result, Netty has succeeded to find a way to achieve ease of development, performance, stability, and flexibility without a compromise.网络
上面一段话引子Netty官网:Netty是一个基于NIO的客户端与服务端框架,可让咱们简单快速的开发协议化的客户端/服务端的网络应用。Netty能够很是简单的进行网络编程,例如TCP和UDP的套接字服务。"快速和简单"并不意味着咱们使用Netty编写的应用很难维护,也不会致使性能问题。Netty的设计很是的谨慎,设计Netty的经验来源于对FTP, SMTP,HTTP以及遗留的各类二进制和基于文本的协议的大量的实现。总之,Netty在实现了快速快发,高性能,稳定性强,易于扩展方面寻找到一种极佳的方式,而不会为了某些因素做出任何的妥协。app
固然,以上只是官网的陈述,笔者发现几乎全部的框架都会使用"简单"、"易于使用"这类的词语,然而笔者在学习Netty的过程当中并不这么认为,多是笔者智商有限吧。那么多的不说了,按照笔者一向的风格,咱们就直接上代码吧。框架
二. Netty入门之HelloWorldsocket
对于Netty来讲,编写一个"Hello World"程序并非那么的简单,对于初学Netty的人来说,可能以为异常的繁琐,怎么说了,繁琐也得学呀,谁让咱走上了编程这条不归路呢?ide
2.1 Netty的启动服务程序函数
public class ServerTest { public static void main(String[] args) throws InterruptedException { /** * bossGroup, 父类的事件循环组只是负责链接,获取到链接后交给 workergroup子的事件循环组, * 参数的获取,业务的处理等工做均是由workergroup这个子事件循环组来完成,一个事件循环组同样 * 能够完成全部的工做,可是Netty推荐的方式是使用两个事件循环组。 */ EventLoopGroup bossGroup = new NioEventLoopGroup(); //建立父事件循环组 EventLoopGroup workerGroup = new NioEventLoopGroup(); //建立子类的事件循环组 try{ //建立启动服务器的对象 ServerBootstrap serverBootstrap = new ServerBootstrap(); /** * group方法接收两个参数, 第一个为父时间循环组,第二个参数为子事件循环组 */ serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) //bossGroup的通道,只是负责链接 .childHandler(new TestChannelnitializer()); //workerGroup的处理器, ChannelFuture channelFuture = serverBootstrap.bind(8899).sync(); //绑定端口 channelFuture.channel().closeFuture().sync(); }finally{ bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
2.2 通道初始化程序oop
通道的初始化程序主要是为workerGroup添加各类Handler.
/** * 初始化一个通道,主要用于设置各类Handler */ public class TestChannelnitializer extends ChannelInitializer<SocketChannel>{ @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); /** * Handler就至关于Servlet中的过滤器, 请求和响应都会走Handler * HttpServerCodec: http的编解码器,用于Http请求和相应 */ pipeline.addLast("httpServerCodec", new HttpServerCodec()); pipeline.addLast("testHttpServerHandler", new TestHttpServerHandler()); } }
2.3 自定义的Handler
/** * 自定义处理器 */ public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject>{ @Override protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { if(msg instanceof HttpRequest){ //要返回的内容, Channel能够理解为链接,而链接中传输的信息要为ByteBuf ByteBuf content = Unpooled.copiedBuffer("Hello World", CharsetUtil.UTF_8); //构造响应 FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); //设置头信息的的MIME类型 response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain"); //内容类型 //设置要返回的内容长度 response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()); //内容长度 //将响应对象返回 ctx.writeAndFlush(response); } } //通道注册成功 @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { System.out.println("channel register..."); super.channelRegistered(ctx); } /** * 自定义的Handler被添加,也就是在TestChannelnitializer的initChannel方法中, * pipeline.addLast("testHttpServerHandler", new TestHttpServerHandler()); * 这行代码执行的时候,该方法被触发 */ @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { System.out.println("handler added..."); super.handlerAdded(ctx); } //通道处于活动状态,便可用状态 @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("channel active..."); super.channelActive(ctx); } //通道处于不活动状态 @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("channel inactive..."); super.channelInactive(ctx); } //通道取消注册 @Override public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { System.out.println("channel unregister..."); super.channelUnregistered(ctx); } }
三.运行
首先启动ServerTest的主函数,而后再网页中输入: http://localhost:88899,就会出现你但愿看到的东西(前提是代码要写对),以下图:
四.总结
不少人可能看到该代码会以为头昏脑胀,谁不是呢?笔者对于编程的学习方式一直都是:不懂就敲,先学会用,仍是不懂,接着敲,直到敲到你认为不少东西理所固然了,就是会了。