Netty系列入门之HelloWorld(一)

一. 简介

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在实现了快速快发,高性能,稳定性强,易于扩展方面寻找到一种极佳的方式,而不会为了某些因素作出任何的妥协。

  当然,以上只是官网的陈述,笔者发现几乎所有的框架都会使用"简单"、"易于使用"这类的词语,然而笔者在学习Netty的过程中并不这么认为,可能是笔者智商有限吧。那么多的不说了,按照笔者一贯的风格,我们就直接上代码吧。

二. Netty入门之HelloWorld

  对于Netty来说,编写一个"Hello World"程序并不是那么的简单,对于初学Netty的人来讲,可能觉得异常的繁琐,怎么说了,繁琐也得学呀,谁让咱走上了编程这条不归路呢?

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 通道初始化程序

  通道的初始化程序主要是为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,就会出现你希望看到的东西(前提是代码要写对),如下图:

四.总结

  很多人可能看到该代码会觉得头昏脑胀,谁不是呢?笔者对于编程的学习方式一直都是:不懂就敲,先学会用,还是不懂,接着敲,直到敲到你认为很多东西理所当然了,就是会了。

Netty入门之HelloWorld的更多相关文章

  1. Netty学习_Netty框架入门教程:Netty入门之HelloWorld实现

    我们可能都学过Socket通信/io/nio/aio等的编程.如果想把Socket真正的用于实际工作中去,那么还需要不断的完善.扩展和优化.比如很经典的Tcp读包写包问题,或者是数据接收的大小,实际的 ...

  2. Netty 系列(三)Netty 入门

    Netty 系列(三)Netty 入门 Netty 是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠性的网络服务器和客户端程序.更多请参考:Netty Github 和 Netty中文 ...

  3. Netty入门之客户端与服务端通信(二)

    Netty入门之客户端与服务端通信(二) 一.简介 在上一篇博文中笔者写了关于Netty入门级的Hello World程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码 ...

  4. Netty入门

    一.NIO Netty框架底层是对NIO的高度封装,所以想要更好的学习Netty之前,应先了解下什么是NIO - NIO是non-blocking的简称,在jdk1.4 里提供的新api,他的他的特性 ...

  5. netty入门(一)

    1. netty入门(一) 1.1. 传统socket编程 在任何时候都可能有大量的线程处于休眠状态,只是等待输入或者输出数据就绪,这可能算是一种资源浪费. 需要为每个线程的调用栈都分配内存,其默认值 ...

  6. Netty入门(三)之web服务器

    Netty入门(三)之web服务器 阅读前请参考 Netty入门(一)之webSocket聊天室 Netty入门(二)之PC聊天室 有了前两篇的使用基础,学习本文也很简单!只需要在前两文的基础上稍微改 ...

  7. Netty入门(二)之PC聊天室

    参看Netty入门(一):Netty入门(一)之webSocket聊天室 Netty4.X下载地址:http://netty.io/downloads.html 一:服务端 1.SimpleChatS ...

  8. Netty入门(一)之webSocket聊天室

    一:简介 Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.高可靠性协议的服务器和客户端. 换句话说,Netty 是 ...

  9. netty同时做http和websocket(netty入门)

    ---恢复内容开始--- http://www.jianshu.com/p/5c29c6c6d28c ---恢复内容结束--- http://www.jianshu.com/p/5c29c6c6d28 ...

随机推荐

  1. NOIP2016提高组初赛(2)四、阅读程序写结果2、

    #include <iostream> using namespace std; int main() { ][], b[][]; ]; string tmp; , j = , k = , ...

  2. c++邻接表存储图(无向),并用广度优先和深度优先遍历(实验)

    一开始我是用c写的,后面才发现广搜要用到队列,所以我就直接使用c++的STL队列来写, 因为不想再写多一个队列了.这次实验写了两个多钟,因为要边写边思考,太菜了哈哈. 主要参考<大话数据结构&g ...

  3. JavaScript中对日期格式化的新想法.

    其实我们对与日期的显示,也就那么几种,不需要每次都传格式化字符串. 只要告诉函数你想要什么结果就好了,以下是在ios的JavaScript中我新写的日期格式化函数: /** 格式化日期 @param ...

  4. 小程序使用wx.chooseAddress获取用户手机号码,微信chooseAddress接口获取用户收货信息

    通常用户在商城购买产品后,需要填写他的收货信息,方便我们发货,但是在手机上写字非常不方便,一个客户的收货信息包括:姓名,地址和手机号码这些内容全部填写的话,至少要写20个字. 地址 所以有些客户在手机 ...

  5. Libcurl的编译_HTTP/HTTPSclient源代码演示样例

    HTTP/HTTPSclient源代码演示样例 环境:  zlib-1.2.8  openssl-1.0.1g  curl-7.36 Author:  Kagula LastUpdateDate: 2 ...

  6. Triangle LeetCode |My solution

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n ...

  7. ajaxSetup设置Ajax请求的默认值

    ajaxSetup() 方法为将来的 AJAX 请求设置默认值.语法$.ajaxSetup({name:value, name:value, ... }) 该参数为带有一个或多个名称/值对的 AJAX ...

  8. Struts的使用

    一.Struts2的获取 Struts的官方网站为:http://struts.apache.org/ 下载完Struts2的jar包,解压,Struts2资源包的目录结构如下图: apps目录下包含 ...

  9. ES6原生Promise的所有方法介绍(附一道应用场景题目)

    JS的ES6已经出来很久了,作为前端工程师如果对此还不熟悉有点说不过去.不过如果要问,Promise原生的api一共有哪几个?好像真的可以难倒一票人,包括我自己也忽略了其中一个不常用的API Prom ...

  10. 《Spark大数据处理:技术、应用与性能优化》【PDF】 下载

    内容简介 <Spark大数据处理:技术.应用与性能优化>根据最新技术版本,系统.全面.详细讲解Spark的各项功能使用.原理机制.技术细节.应用方法.性能优化,以及BDAS生态系统的相关技 ...