Netty中的编解码框架

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_25484147/article/details/85312497

为何使用编解码框架

我的理解是在网络应用程序中,只能是通过字节传输,这么就会造成一个问题,在目标应用程序之间需要对字节转化为各个程序需要的数据类型,这个事情就是由编解码器做的处理。编码器做的是将数据类型转化为字节,而解码器就是将字节转化为各种数据类型。

解码器

在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

猜你喜欢

转载自blog.csdn.net/qq_25484147/article/details/85312497