8.Netty框架与Marshalling解编码框架结合案例之发送压缩文件

博客概述

本博客中的代码将使用java自带的压缩技术gzip对文件进行压缩,然后通过Marshalling框架对文件进行发送。需要注意的是Marshalling解码器在发送文件的场景,长度需要设置的大一些。本案例是在上一个案例基础上进行的,此处只给出变动的代码。

压缩帮助类

package utils;

import java.io.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * @Auther: ;李泽
 * @Date: 2019/3/12 20:05
 * @Description:
 */
public class GzipsUtils {
    /**
     * 功能描述: 数据压缩函数
     *
     * @auther: 李泽
     * @date: 2019/3/12 20:09
     */
    public static byte[] gzip(byte[] data) throws Exception{
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
        gzipOutputStream.write(data);
        gzipOutputStream.finish();
        gzipOutputStream.close();
        byte[] bytes = outputStream.toByteArray();
        outputStream.close();
        return bytes;
    }
    /**
     * 功能描述: 数据解压缩
     *
     * @auther: 李泽
     * @date: 2019/3/12 22:42
     */
    public static byte[] unzip(byte[] data) throws Exception{
        ByteArrayInputStream bis = new ByteArrayInputStream(data);
        GZIPInputStream gzip = new GZIPInputStream(bis);
        byte[] buf = new byte[1024];
        int num = -1;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while ((num = gzip.read(buf,0,buf.length))!=-1){
            bos.write(buf,0,num);
        }
        gzip.close();
        bis.close();
        byte[] ret = bos.toByteArray();
        bos.flush();
        bos.close();
        return ret;
    }
    /**
     * 功能描述: 测试
     *
     * @auther: 李泽
     * @date: 2019/3/12 22:48
     */
    public static void main(String[] args) throws Exception {
        //读取文件
        String readPath  =System.getProperty("user.dir")+ File.separatorChar+"sources"+ File.separatorChar+"006.jpg";
        File file = new File(readPath);
        FileInputStream fis = new FileInputStream(file);
        byte[] data = new byte[fis.available()];
        fis.read(data);
        fis.close();
        System.out.println("文件原生大小"+data.length);
        //测试压缩
        byte[] ret1 = GzipsUtils.gzip(data);
        System.out.println("文件压缩后大小"+ret1.length);
        //还原
        byte[] ret2 = GzipsUtils.unzip(ret1);
        System.out.println("文件还原后大小"+ret2.length);
        //写出文件
        String writePath  =System.getProperty("user.dir")+ File.separatorChar+"receive"+ File.separatorChar+"006.jpg";
        FileOutputStream fos = new FileOutputStream(writePath);
        fos.write(ret2);
        fos.close();
    }
}

客户端

package marshalling;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import utils.GzipsUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

/**
 * @Auther: ;李泽
 * @Date: 2019/3/4 22:05
 * @Description:
 */
public class NettyClient {
    public static void main(String[] args) throws Exception {
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(eventLoopGroup)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        //设置Marshalling解编码器。
                        socketChannel.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
                        socketChannel.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
                        //这里面的是接受服务器端反馈时,才会触发的handler
                        socketChannel.pipeline().addLast(new ClientHandler());
                    }
                });
        ChannelFuture channelFuture1 = bootstrap.connect("127.0.0.1",8080).sync();
        //客户端发送数据,因为用了解编码框架
        for (int i = 0; i < 5; i++) {
            Request request = new Request();
            request.setId(i+"");
            request.setName("item"+i);
            request.setRequestMessage("i am msg"+i);
            String readPath  =System.getProperty("user.dir")+ File.separatorChar+"sources"+ File.separatorChar+"006.jpg";
            File file = new File(readPath);
            FileInputStream fis = new FileInputStream(file);
            byte[] data = new byte[fis.available()];
            fis.read(data);
            fis.close();
            request.setAttachment(GzipsUtils.gzip(data));
            channelFuture1.channel().writeAndFlush(request);
        }


        //可以理解为阻塞在这
        channelFuture1.channel().closeFuture().sync();
        eventLoopGroup.shutdownGracefully();
    }
}

服务端handler

package marshalling;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;
import utils.GzipsUtils;

import java.io.File;
import java.io.FileOutputStream;


/**
 * @Auther: ;李泽
 * @Date: 2019/3/4 22:05
 * @Description:  继承自ChannelHandlerAdapter,这个类实现了ChannelHandler接口,ChannelHandler提供了许多事件处理
 *                的接口方法,然后你可以覆盖这些方法。现在仅仅只需要继承ChannelHandlerAdapter类而不是你自己去实
 *                现接口方法。
 */
public class ServerHandler extends ChannelHandlerAdapter {
    /**
     * 功能描述: exceptionCaught()事件处理方法是当出现Throwable对象才会被调用,即当Netty由于IO错误或者处理器在处理事件
     *           时抛出的异常时。在大部分情况下,捕获的异常应该被记录下来并且把关联的channel给关闭掉。然而这个方法的处
     *           理方式会在遇到不同异常的情况下有不同的实现,比如你可能想在关闭连接之前发送一个错误码的响应消息。
     *
     * @auther: 李泽
     * @date: 2019/3/4 22:24
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
    }
    /**
     * 功能描述: 这里我们覆盖了chanelRead()事件处理方法。每当从客户端收到新的数据时,这个方法会在收到消息时被调用,
     *           这个例子中,收到的消息的类型是Request,因为我们使用了解编码框架
     *
     * @auther: 李泽
     * @date: 2019/3/4 22:23
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //接收数据
        Request request = (Request) msg;
        System.out.println("request = " + request);
        String writePath  =System.getProperty("user.dir")+ File.separatorChar+"receive"+ File.separatorChar+"006.jpg";
        FileOutputStream fos = new FileOutputStream(writePath);
        fos.write(GzipsUtils.unzip(request.getAttachment()));
        fos.close();
        //回写数据
        Response response = new Response();
        response.setId(request.getId());
        response.setName("resp "+request.getName());
        response.setResponseMessage("resp "+request.getRequestMessage());
        ctx.writeAndFlush(response);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值