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. Could not load file or assembly ‘ Oracle.ManagedDataAccess.EntityFramework, Version=6.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342’ or one of its dependencies系统找不到指定文件 处理方法

    前些天做EF Model-First测试,开发环境为VS2013,数据库为Oracle 11g.所有东西都装好数据模型已经建立后准备执行“根据模型生成数据库”命令时,出现:Could not load ...

  2. oracle 备份数据库,导出数据库

    导出数据库 exp hljslfh2/hljslfh@dbsvr file=d:\hljslfh2Of0426.dmp 导入数据库 imp hljslfh2/hljslfh@localhost/dbs ...

  3. hadoop 用户

    上篇文章说过,hadoop实际上就是就是一个liunx虚拟机,它的文件操作命令同linux,而它的用户呢?它的用户实际上就是linux主机的用户.这里我们做的例子就是:新建一个liunx用户,并为该l ...

  4. 环境配置问题: 关于IDEA配置tomcat

    1. 先下载并解压缩一个tomcat7 2.打开idea 3. -Xms256M -Xmx1024M -XX:PermSize=64M -XX:MaxPermSize=128M 关于热部署设置参考:  ...

  5. oracle配置数据库可恢复性(认证系列总结一)

    原创作品,转载请注明出处:https://www.cnblogs.com/sunshine5683/p/10263246.html 接下来的n多天,将进入oracle认证系列的学习总结中,本该从asm ...

  6. ubuntu16.04下安装mysql,并开启远程访问

    一.安装 apt-get install mysql-server 二.本地连接 mysql默认开启了本地连接 直接通过mysql -uuser -p,然后输入密码访问 三.开启远程访问 3.1.创建 ...

  7. Flask如何给多个视图函数增加装饰器

    这几天在学习Flask, 遇到了些小问题,比如说怎么给多个视图函数加相同的装饰器 给单独一个视图函数加装饰器的话很简单,写一个装饰器,然后直接加在原装饰器下面即可,多个的话,会报这样一个错误: 这个异 ...

  8. CSS计数器(序列数字字符自动递增)详解———张鑫旭

    by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=4303 一.挖坟不可耻 ...

  9. PHP实现大转盘抽奖算法

    流程: 1.拼装奖项数组,2.计算概率,3.返回中奖情况 代码如下:中奖概率 ' v ' 可以在后台设置,传到此方法中,注意传整数 function get_gift(){ //拼装奖项数组 // 奖 ...

  10. javascript 数组求交集/差集/并集/过滤重复

    最近在小一个小程序项目,突然发现 javscript 对数组支持不是很好,连这些基本的功能,都还要自己封装.网上查了下,再结合自己的想法,封装了一下,代码如下. //数组交集 Array.protot ...