名称 |
描述 |
httprequestEncoder |
将 httprequest、httpContent 和 LasthttpContent 消息编码为字节 |
httpResponseEncoder |
将 httpResponse、httpContent 和 LasthttpContent 消息编码为字节 |
httprequestDecoder |
将字节编码为 httprequest、httpContent 和 LasthttpContent 消息 |
httpResponseDecoder |
将字节编码为 httpResponse、httpContent 和 LasthttpContent 消息 |
@H_616_56@
下述代码中的 httpPipelineInitializer 类展示了将 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) {
// 如果是客户端,则添加 httpResponseDecoder 处理来自服务器的响应
pipeline.addLast("decoder", new httpResponseDecoder());
// 如果是客户端,则添加 httprequestEncoder 向服务器发送请求
pipeline.addLast("encoder", new httprequestEncoder());
} else {
// 如果是服务端,则添加 httprequestDecoder 处理来自客户端的请求
pipeline.addLast("decoder", new httprequestDecoder());
// 如果是客户端,则添加 httpResponseEncoder 向客户端发送响应
pipeline.addLast("encoder", new httpResponseEncoder());
}
}
}
在 ChAnnelInitializer 将 ChAnnelHandler 安装到 ChAnnelPipeline 中之后,你就可以处理不同类型的 httpObject 消息了。但由于 http 请求和响应可能由许多部分组成,因此你需要聚合它们以形成完整的消息。Netty 提供了一个聚合器,它可以将多个消息部分合并为 Fullhttprequest 或者 FullhttpResponse 消息
由于消息分段需要被缓冲,直到可以转发下一个完整的消息给下一个 ChAnnelInboundHandler,所以这个操作有轻微的开销,其所带来的好处就是你可以不必关心消息碎片了
引入这种自动聚合机制只不过是向 ChAnnelPipeline 中添加另外一个 ChAnnelHandler 罢了,下述代码展示了如何做到这一点:
public class httpAggregatorInitializer extends ChAnnelInitializer<ChAnnel> {
private final Boolean isClient;
public httpAggregatorInitializer(Boolean isClient) {
this.isClient = isClient;
}
@Override
protected void initChAnnel(ChAnnel ch) throws Exception {
ChAnnelPipeline pipeline = ch.pipeline();
if (isClient) {
// 如果是客户端,则添加 httpClientCodec
pipeline.addLast("codec", new httpClientCodec());
} else {
// 如果是服务器,则添加 httpServerCodec
pipeline.addLast("codec", new httpServerCodec());
}
// 将最大的消息大小为 512KB 的 httpObjectAggregator 添加到 ChAnnelPipeline
pipeline.addLast("aggregator", new httpObjectAggregator(512 * 1024));
}
}
当使用 http 时,建议开启压缩功能以尽可能多地减小传输数据的大小。虽然压缩会带来一些消耗,但通常来说它都是一个好主意,尤其是对于文本数据而言
Netty 为压缩和解压都提供了 ChAnnelHandler 实现,它们同时支持 gzip 和 deflate 编码
客户端可以通过提供以下头部信息来指示服务器它所支持的压缩格式
GET /encrypted-area http/1.1
Host: www.example.com
Accept-Encoding: gzip, deflate
然而,需要注意的是,服务器没有义务压缩它所发送的数据
public class httpCompressionInitializer extends ChAnnelInitializer<ChAnnel> {
private final Boolean isClient;
public httpCompressionInitializer(Boolean isClient) {
this.isClient = isClient;
}
@Override
protected void initChAnnel(ChAnnel ch) throws Exception {
ChAnnelPipeline pipeline = ch.pipeline();
if (isClient) {
// 如果是客户端,则添加 httpClientCodec
pipeline.addLast("codec", new httpClientCodec());
// 如果是客户端,则添加 httpContentDecompressor 以处理来自服务器的压缩内容
pipeline.addLast("decompressor", new httpContentDecompressor());
} else {
// 如果是服务端,则添加 httpServerCodec
pipeline.addLast("codec", new httpServerCodec());
// 如果是服务器,则添加 httpContentDecompressor 来压缩数据
pipeline.addLast("decompressor", new httpContentDecompressor());
}
}
}
启用 httpS 只需要将 SslHandler 添加到 ChAnnelPipeline 的 ChAnnelHandler 组合中
public class httpsCodecInitializer extends ChAnnelInitializer<ChAnnel> {
private final SslContext context;
private final Boolean isClient;
public httpsCodecInitializer(SslContext context, Boolean isClient) {
this.context = context;
this.isClient = isClient;
}
@Override
protected void initChAnnel(ChAnnel ch) throws Exception {
ChAnnelPipeline pipeline = ch.pipeline();
SSLENGIne ENGIne = context.newENGIne(ch.alloc());
pipeline.addLast("ssl", new SslHandler(ENGInE));
if (isClient) {
pipeline.addLast("codec", new httpClientCodec());
} else {
pipeline.addLast("codec", new httpServerCodec());
}
}
}
WebSocket
WebSocket 解决了一个长期存在的问题:既然底层协议(http)是一个请求/响应模式的交互序列,那么如何实时地发布信息呢?AJAX一定程度上解决了这个问题,但数据流仍然是由客户端所发送的请求驱动的
WebSocket 提供了在单个 TCP 连接上提供双向的通信,它为网页和远程服务器之间的双向通信提供了一种替代 http 轮询的方案
要想向你的应用程序添加对于 WebSocket 的支持,你需要将适当的客户端或者服务器 WebSocketChAnnelHandler 添加到 ChAnnelPipeline 中。这个类将处理由 WebSocket 定义的称为帧的特殊消息类型,如表所示,WebSocketFrame 可以被归类为数据帧或者控制帧
名称 |
描述 |
BinaryWebSocketFrame |
数据帧:二进制数据 |
TextWebSocketFrame |
数据帧:文本数据 |
ConTinuationWebSocketFrame |
数据帧:属于上一个 BinaryWebSocketFrame 或者 TextWebSocketFrame 的文本或者二进制的数据 |
CloseWebSocketFrame |
控制帧:一个 CLOSE 请求,关闭的状态码以及关闭的原因 |
PingWebSocketFrame |
控制帧:请求一个 PongWebSocketFrame |
PongWebSocketFrame |
控制帧:对 PingWebSocketFrame 请求的响应 |
@H_616_56@
因为 Netty 主要是一种服务器端技术,所以我们重点创建 WebSocket 服务器。下述代码展示了使用 WebSocketChAnnelHandler 的简单示例,这个类会处理协议升级握手,以及三种控制帧 —— Close、Ping 和 Pong,Text 和 Binary 数据帧将会被传递给下一个 ChAnnelHandler 进行处理
public class WebSocketServerInitializer extends ChAnnelInitializer<ChAnnel> {
@Override
protected void initChAnnel(ChAnnel ch) throws Exception {
ch.pipeline().addLast(
new httpServerCodec(),
new httpObjectAggregator(65536),
// 如果被请求的端点是 /websocket,则处理该升级握手
new WebSocketServerProtocolHandler("/websocket"),
// TextFrameHandler 处理 TextWebSocketFrame
new TextFrameHandler(),
// BinaryFrameHandler 处理 BinaryWebSocketFrame
new BinaryFrameHandler(),
// ConTinuationFrameHandler 处理 ConTinuation WebSocketFrame
new ConTinuationFrameHandler());
}
public static final class TextFrameHandler extends SimpleChAnnelInboundHandler<TextWebSocketFrame> {
@Override
protected void messageReceived(ChAnnelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
// do something
}
}
public static final class BinaryFrameHandler extends SimpleChAnnelInboundHandler<BinaryWebSocketFrame> {
@Override
protected void messageReceived(ChAnnelHandlerContext ctx, BinaryWebSocketFrame msg) throws Exception {
// do something
}
}
public static final class ConTinuationFrameHandler extends SimpleChAnnelInboundHandler<ConTinuationWebSocketFrame> {
@Override
protected void messageReceived(ChAnnelHandlerContext ctx, ConTinuationWebSocketFrame msg) throws Exception {
// do something
}
}
}
大佬总结
以上是大佬教程为你收集整理的Netty 框架学习 —— 基于 Netty 的 HTTP/HTTPS 应用程序全部内容,希望文章能够帮你解决Netty 框架学习 —— 基于 Netty 的 HTTP/HTTPS 应用程序所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。