文章目录
为何使用编解码框架
我的理解是在网络应用程序中,只能是通过字节传输,这么就会造成一个问题,在目标应用程序之间需要对字节转化为各个程序需要的数据类型,这个事情就是由编解码器做的处理。编码器做的是将数据类型转化为字节,而解码器就是将字节转化为各种数据类型。
解码器
在Netty中解码器有两种方式,一种是将字节转化为各种数据类型:ByteToMessageDecoder 和ReplayingDecoder。一种是一种数据类型转化为另外一种数据类型:MessageToMessageDecoder。
ByteToMessageDecoder
package com.bobo.netty.codec;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.util.List;
/**
* ByteToMessage的扩展类
* @author [email protected]
* @create 2018-12-27 22:51
**/
public class ByteToMessageImpl extends ByteToMessageDecoder{
/**
* 这个方法被调用的时候将会传入一个包含了传入数据的ByteBuf,
* 以及一个用来添加解码消息的List,对这个方法的调用将会反复进行,
* 直到确定没有新的元素添加到该List,或者该ByteBuf中没有更多
* 可读取的字节位置,如果这个List不为空,那么它的内容将会传递到
* ChannelPipeline中的下一个ChannelInboundHandler
* @param ctx
* @param in
* @param out
* @throws Exception
*/
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
// 检查是否至少有4个字节可读
if (in.readableBytes() >= 4) {
//将传入的字节转化为int类型,放在List中,
//然后传递到ChannelPipeLine中的下一个ChannelInboundHandler
out.add(in.readInt());
}
}
/**
* 当Channel的状态变成为非活动的时候,这个方法就会被调用一次
* @param ctx
* @param in
* @param out
* @throws Exception
*/
@Override
protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
}
}
ReplayingDecoder
package com.bobo.netty.codec;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;
import java.util.List;
/**
* ReplayingDecoder实现类
* @author [email protected]
* @create 2018-12-28 9:47
**/
public class ReplayingDecoderImpl extends ReplayingDecoder<Void> {
/**
* 通过这个类,可以不用去调用readableBytes,
*
* @param ctx
* @param in
* @param out
* @throws Exception
*/
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
out.add(in.readInt());
}
}
当没有足够的字节可以使用的使用,这个in.readInt方法就会抛出一个Error,其将在基类中被捕获并且处理,当由恩过可读数据的时候,这个decode方法将再一次被调用。
注意:1.并不是所有的ByteBuf 操作都被支持,如果调用了一个不被支持的方法,将会抛出一
个UnsupportedOperationException。2.ReplayingDecoder 稍慢于ByteToMessageDecoder。
抽象类MessageToMessageDecoder
这里说的是如何将一个实体转化为另一个实体。
package com.bobo.netty.codec;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.util.List;
/**
* 将一个实体转化为另一个实体
* @author [email protected]
* @create 2018-12-28 10:13
**/
public class MessageToMessageDecoderImpl extends MessageToMessageDecoder<Integer> {
/**
* 这里是将一个Integer转化为String类型
* @param ctx
* @param msg
* @param out
* @throws Exception
*/
@Override
protected void decode(ChannelHandlerContext ctx, Integer msg, List<Object> out) throws Exception {
out.add(String.valueOf(msg));
}
}
TooLongFrameException 类
由于Netty 是一个异步框架,所以需要在字节可以解码之前在内存中缓冲它们。因此,不能让解码器缓冲大量的数据以至于耗尽可用的内存。为了解除这个常见的顾虑,Netty 提供了TooLongFrameException 类,其将由解码器在帧超出指定的大小限制时抛出。
编码器
MessageToByteEncoder
package com.bobo.netty.codec;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
/**
* 编码器实现
*
* @author [email protected]
* @create 2018-12-28 10:25
**/
public class MessageToByteEncoderImpl extends MessageToByteEncoder<Short>{
/**
* 将数据实体转化为字节
* @param ctx
* @param msg
* @param out
* @throws Exception
*/
@Override
protected void encode(ChannelHandlerContext ctx, Short msg, ByteBuf out) throws Exception {
out.writeShort(msg);
}
}
MessageToMessageEncoder
package com.bobo.netty.codec;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import java.util.List;
/**
* MessageToMessageEncoder的实现类
* @author [email protected]
* @create 2018-12-28 10:27
**/
public class MessageToMessageEncoderImpl extends MessageToMessageEncoder<Integer> {
/**
* 这里展示了将一个Integer类型的String写入到List中
* @param ctx
* @param msg
* @param out
* @throws Exception
*/
@Override
protected void encode(ChannelHandlerContext ctx, Integer msg, List<Object> out) throws Exception {
out.add(String.valueOf(msg));
}
}
Netty中预置的编解码器
通过SSL/TLS保护Netty应用程序
基于HTTP/HTTPS的 应用程序
HTTP解码器
HTTP请求的组成成分
HTTP响应的组成部分
HTTP编码器和解码器
这一块儿暂时不是很懂,所以先留着这里,如果需要的时候再学习
名称 | 描述 |
---|---|
HttpRequestEncoder | 将HttpRequest、HttpContent 和LastHttpContent 消息编码为字节 |
HttpResponseEncoder | 将HttpResponse、HttpContent 和LastHttpContent 消息编码为字节 |
HttpRequestDecoder | 将字节解码为HttpRequest、HttpContent 和LastHttpContent 消息 |
HttpResponseDecoder | 将字节解码为HttpResponse、HttpContent 和LastHttpContent 消息 |
HttpObjectAggregator | 聚合HTTP消息 |
HttpContentDecompressor | 处理来自服务器的压缩内容 |
HttpContentCompressor | 在服务器端压缩数据 |
SslHandler | 使用HTTPS |
空闲的连接和超时
检测空闲连接以及超时对于及时释放资源来说是至关重要的。由于这是一项常见的任务,
Netty 特地为它提供了几个ChannelHandler 实现。
名称 | 描述 |
---|---|
IdleStateHandler | 当连接空闲时间太长时,将会触发一个IdleStateEvent 事件。然后,你可以通过在你的ChannelInboundHandler 中重写userEvent-Triggered()方法来处理该IdleStateEvent 事件 |
ReadTimeoutHandler | 如果在指定的时间间隔内没有收到任何的入站数据,则抛出一个Read-TimeoutException 并关闭对应的Channel。可以通过重写你的ChannelHandler 中的exceptionCaught()方法来检测该Read-TimeoutException |
WriteTimeoutHandler | 如果在指定的时间间隔内没有任何出站数据写入,则抛出一个Write-TimeoutException 并关闭对应的Channel 。可以通过重写你的ChannelHandler 的exceptionCaught()方法检测该WriteTimeout-Exception |