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. 学习图像算法阶段性总结 (附一键修图Demo)

    今天特别感慨.自己从决定研究图像处理.势必要做出一键修图算法. 经历了,三个多月的书籍积累,三个多月的算法调整以及优化. 人是一种奇怪的动物.当你做不到的时候,你以为做到了.自己会感觉非常爽,非常有成 ...

  2. 【Notification】屏蔽特定应用的通知提示

    须要默认屏蔽特定app的通知提示 设置app是否接收通知的界面 点击每一个条目进去的界面 AppNotificationSettings extends SettingsPreferenceFragm ...

  3. Vue深度学习(5)-过渡效果

    简介 通过 Vue.js 的过渡系统,你可以轻松的为 DOM 节点被插入/移除的过程添加过渡动画效果.Vue 将会在适当的时机添加/移除 CSS 类名来触发 CSS3 过渡/动画效果,你也可以提供相应 ...

  4. F12调试模式下使用console自动提交

    F12调试模式下使用console自动提交(F12 的console->输入代码->按enter即可运行) 1.使用定时器setInterval进行自动提交 //方法中可使用jquery调 ...

  5. linux 安装tensorflow(gpu版本)

    一.安装cuda 具体安装过程见我的另一篇博客,ubuntu16.04下安装配置深度学习环境 二.安装tensorflow 1.具体安装过程官网其实写的比较详细,总结一下的话可以分为两种:安装rele ...

  6. Spring依赖注入原理

    接触过spring 的同学应该都知道依赖注入,依赖注入又称控制反转,其内涵就是,将创建某个bean的控制权力,由原来需要引用这个bean的bean转移(反转)到外部的spring IOC容器,由IOC ...

  7. reference file contains errors

    一,问题分析 在学习 JavaWeb 的开发,很多时候我们会引用许多 JAR ,以为版本的问题,有时候就会出现这个问题:reference file contains errors (引用文件包含错误 ...

  8. C# 委托详解(一)

    1.委托简单例子 class eeProgram { // 声明delegate对象 public delegate string CompareDelegate(int a, int b); // ...

  9. HTML5 桌面通知:Notification API

    原文地址:http://blog.gdfengshuo.com/article/23/ 前言 Notification API 是 HTML5 新增的桌面通知 API,用于向用户显示通知信息.该通知是 ...

  10. Data Base mongodb高版本与低版本的区别

    mongodb高版本与低版本的区别 一.mongodb引擎: Mongodb 3.0支持用户自定义存储引擎,用户可配置使用mmapv1或者wiredTiger存储引擎. 3.2版本以后默认的开启的是w ...