HTTP/HTTPS 是最常见的一种协议,这节主要是看一下 Netty 提供的 ChannelHaandler。

一、HTTP Decoder,Encoder 和 Codec

  HTTP 是请求-响应模式,客户端发送一个 HTTP 请求,服务就响应此请求。

  HttpRequest 包格式如下:

  

  1. 包头
  2. 数据部分,后续可以有多个 HttpContent 部分
  3. 包尾,标记 request 包结束,同时可能包含头的尾部信息
  4. 完整的 HTTP request

  HttpResponce 包格式如下:

  

  1. 包头
  2. 数据部分,后续可以有多个 HttpContent 部分
  3. 包尾,标记 responce 包结束,同时可能包含头的尾部信息
  4. 完整的 HTTP responce

  下面是 Netty 提供的解码器和编码器用来处理上述的包信息:

  

  所以,如果我们想要在应用程序中支持 HTTP,只需要添加正确的 ChannelHandler 到 ChannelPipeline 中即可:

 public class HttpPipelineInitializer extends ChannelInitializer<Channel> {
private final boolean client; public HttpPipelineInitializer(boolean client) {
this.client = client;
} @Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
if(client) {
// 客户端需要解码服务器响应,编码客户端请求
pipeline.addLast("decoder", new HttpResponseDecoder());
pipeline.addLast("encoder", new HttpRequestEncoder());
} else {
// 服务端需要解码客户端请求,编码服务端响应
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("encoder", new HttpResponseEncoder());
}
} }

二、HTTP 消息聚合

  由于 HTTP 请求和响应消息部分可以由许多块组成,我们需要聚合它们形成完整的消息。Netty 提供了一个聚合器。如下为简单实现:

 /**
* HTTP 消息聚合
* HttpObjectAggregator
*/
public class HttpAggregatorInitializer extends ChannelInitializer<Channel> {
private final boolean client; public HttpAggregatorInitializer(boolean client) {
this.client = client;
} @Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
if(client) {
// 客户端
pipeline.addLast("codec", new HttpClientCodec());
} else {
// 服务器
pipeline.addLast("codec", new HttpServerCodec());
}
// HTTP聚合,设置最大消息值为512KB
pipeline.addLast("aggegator", new HttpObjectAggregator(512 * 1024));
} }

三、HTTP 压缩

  使用 HTTP 时建议压缩数据以减少传输流量,Netty 支持 “gzip”和“deflate”。简单实现如下:

 /**
* HTTP 压缩
* HttpContentDecompressor 用于客户端解压缩
* HttpContentCompressor 用于服务器压缩
*/
public class HttpCompressorInitializer extends ChannelInitializer<Channel> {
private final boolean client; public HttpCompressorInitializer(boolean client) {
this.client = client;
} @Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
if(client) {
// 客户端
pipeline.addLast("codec", new HttpClientCodec());
// 解压缩,用于处理来自服务器的压缩内容
pipeline.addLast("decompressor", new HttpContentDecompressor());
} else {
// 服务端
pipeline.addLast("codec", new HttpServerCodec());
// 压缩,将要发送的消息压缩后再发出
pipeline.addLast("compressor", new HttpContentCompressor());
}
} }

四、使用 HTTPS

  启动 HTTPS(比 HTTP 安全),只需添加 SslHandler。简单实现如下:

 /**
* HTTPS
*/
public class HttpsCodecInitializer extends ChannelInitializer<Channel> {
private final SslContext context;
private final boolean client; public HttpsCodecInitializer(SslContext context, boolean client) {
this.context = context;
this.client = client;
} @Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
SSLEngine engine = context.newEngine(ch.alloc()); // 添加SslHandler以启用HTTPS
pipeline.addFirst("ssl", new SslHandler(engine));
if(client) {
// 客户端
pipeline.addLast("codec", new HttpClientCodec());
} else {
// 服务端
pipeline.addLast("codec", new HttpServerCodec());
}
} }

五、WebSocket

  WebSocket 允许数据双向传输,而不需要请求-响应模式。当我们需要服务器主动向客户端发送消息,比如实时系统,WebSocket 就是一个不错的选择。下面是一个通用的 WebSocket 协议:

  

  1. Client(HTTP)与 Server 通讯
  2. Server(HTTP)与 Client 通讯
  3. Client 通过 HTTP(s) 来进行 WebSocket 握手,并等待确认
  4. 连接协议升级至 WebSocket

  应用程序支持 WebSocket 只需要添加适当的客户端或服务器端 WebSocket ChannelHandler 到管道。这个类将处理 WebSocket 定义的信息类型,称为“帧”。帧类型可分为数据帧和控制帧,如下:

  

  简单实现如下:

 /**
* WebSocket
* WebSocketServerProtocolHandler 处理其他类型帧
* TextFrameHandler BinaryFrameHandler ContinuationFrameHandler
*/
public class WebSocketServerInitializer extends ChannelInitializer<Channel> { @Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(
new HttpServerCodec(),
new HttpObjectAggregator(65536), // HTTP 聚合
// 处理除指定Frame之外的其他类型帧,比如Ping,Pong,Close等
new WebSocketServerProtocolHandler("/websocket"),
new TextFrameHandler(),
new BinaryFrameHandler(),
new ContinuationFrameHandler());
} // Text Frame
public static final class TextFrameHandler
extends SimpleChannelInboundHandler<TextWebSocketFrame> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
// TODO Handle Text Frame
}
} // Binary Frame
public static final class BinaryFrameHandler
extends SimpleChannelInboundHandler<BinaryWebSocketFrame> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, BinaryWebSocketFrame msg) throws Exception {
// TODO Handle Text Frame
}
} // Continuation Frame
public static final class ContinuationFrameHandler
extends SimpleChannelInboundHandler<ContinuationWebSocketFrame> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, ContinuationWebSocketFrame msg) throws Exception {
// TODO Handle Text Frame
}
}
}

Netty入门(八)构建Netty HTTP/HTTPS应用的更多相关文章

  1. Netty入门教程——认识Netty

    什么是Netty? Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架. Netty 是一个广泛使用的 Java 网络编程框架(N ...

  2. Netty入门教程:Netty拆包粘包技术讲解

    Netty编解码技术是什么意思呢?所谓的编解码技术,说白了就是java序列化技术.序列化有两个目的: 1.进行网络传输2.对象持久化 虽然我们可以使用java进行序列化,Netty去传输.但是java ...

  3. 深入了解Netty【六】Netty工作原理

    引言 前面学习了NIO与零拷贝.IO多路复用模型.Reactor主从模型. 服务器基于IO模型管理连接,获取输入数据,又基于线程模型,处理请求. 下面来学习Netty的具体应用. 1.Netty线程模 ...

  4. Java IO学习笔记八:Netty入门

    作者:Grey 原文地址:Java IO学习笔记八:Netty入门 多路复用多线程方式还是有点麻烦,Netty帮我们做了封装,大大简化了编码的复杂度,接下来熟悉一下netty的基本使用. Netty+ ...

  5. Netty入门与实战教程总结分享

    前言:都说Netty是Java程序员必须要掌握的一项技能,带着不止要知其然还要知其所以然的目的,在慕课上找了一个学习Netty源码的教程,看了几章后着实有点懵逼.虽然用过Netty,并且在自己的个人网 ...

  6. (入门篇 NettyNIO开发指南)第三章-Netty入门应用

    作为Netty的第一个应用程序,我们依然以第2章的时间服务器为例进行开发,通过Netty版本的时间服务报的开发,让初学者尽快学到如何搭建Netty开发环境和!运行Netty应用程序. 如果你已经熟悉N ...

  7. netty 入门(一)

    netty Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序.更确切的讲是一个组件,没有那么复杂. 例子 一  Discard服务器端 我们 ...

  8. Netty入门

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

  9. 高性能NIO框架Netty入门篇

    http://cxytiandi.com/blog/detail/17345 Netty介绍 Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具 ...

  10. Netty 系列(三)Netty 入门

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

随机推荐

  1. C#快速读写文件

    一.写入 //在应用程序当前目录下的File1.txt文件中追加文件内容,如果文件不存在就创建,默认编码 File.AppendAllText("File1.txt", " ...

  2. Extjs 项目中常用的小技巧,也许你用得着(4)---Extjs 中的cookie设置

    1.ExtJs设置cookie两种方式 其一:设置cookie如下 saveacct=isForm.getForm().findField('itemselector').getValue(); Ex ...

  3. C#基础知识回顾--委托事件

    在上一篇看到他我一下子就悟了(续)---委托,被人狂喷.说写的太空,没有什么内容之类的.所以准备在这里重写下,不过还是按着以前的方式尽量简单的写.这里我们以打篮球为例. 第一步:首先,其他对象订购事件 ...

  4. SQL Server 数据库基础知识

    数据库(Database)是由文件管理系统发展起来的,按照数据结构来组织.存储和管理数据的建立在计算机存储设备上的仓库. 特点:       尽可能小的冗余度.       具有较高的数据独立性和易扩 ...

  5. FORM中使用onSubmit="return false"防止表单自动提交,以及submit和button提交表单的区别

    在页面中有多个input type="text"的文本输入框的情况下没有问题,但是当页面中有只有一个文本框的情况下(),就会出现此问题. 后来在form 中添加:onsubmit= ...

  6. 集合框架(TreeSet原理)

    特点: TreeSet是用来排序的,可以指定一个顺序,对象存入之后会按照指定的顺序排列 使用方式: 自然排序(Comparable) TreeSet类的add()方法中会把存入的对象提升为Compar ...

  7. python中的赋值与深浅拷贝的区别

    import copy lt = [1, 2, [3, 4]] # 赋值会增加一个引用,访问的都是同一数据 # lt2 = lt # 浅拷贝:只拷贝对象本身,里面的元素只会增加一个引用 lt2 = l ...

  8. css3 之 display 属性

    1.定义 语法:display:none | inline | block | list-item | inline-block | table | inline-table | table-capt ...

  9. Linux 配置iso系统盘为本地yum源

    Linux配置iso系统盘为本地yum源 by:授客 QQ:1033553122   1.目的 安装软件时,经常会遇到包或类库的依赖性问题,为此,我们可以通过yum命令安装软件,尽量避免出现繁琐的软件 ...

  10. AsyncTask 处理耗时操作&&显示进度条

    在Android中实现异步任务机制有两种,Handler和AsyncTask.优缺点自己百度,推荐使用AsyncTask. private ProgressDialog dialog; //新建一个对 ...