netty: marshalling传递对象,传输附件GzipUtils

前端与服务端传输文件时,需要双方需要进行解压缩,也就是Java序列化。可以使用java进行对象序列化,netty去传输,但java序列化硬伤太多(无法跨语言,码流太大,性能太低),所以最好使用主流的编辑码框架来配合netty使用。此处使用的是JBossMarshalling框架。
用到的包:

<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha2</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.jboss.marshalling/jboss-marshalling -->
<dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling</artifactId>
<version>2.0.0.CR1</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.jboss.marshalling/jboss-marshalling-serial -->
<dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling-serial</artifactId>
<version>2.0.0.CR1</version>
</dependency>

  

用到的压缩包工具类:

gziputils.java

public class GzipUtils {

	 public static byte[] gzip(byte[] data) throws Exception{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(bos);
gzip.write(data);
gzip.finish();
gzip.close();
byte[] ret = bos.toByteArray();
bos.close();
return ret;
} public static byte[] ungzip(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;
} public static void main(String[] args) throws Exception{ //读取文件
String readPath = System.getProperty("user.dir") + File.separatorChar + "sources" + File.separatorChar + "Netty+3.1中文用户手册.doc.jpg";
File file = new File(readPath);
FileInputStream in = new FileInputStream(file);
byte[] data = new byte[in.available()];
in.read(data);
in.close(); System.out.println("文件原始大小:" + data.length);
//测试压缩 byte[] ret1 = GzipUtils.gzip(data);
System.out.println("压缩之后大小:" + ret1.length); byte[] ret2 = GzipUtils.ungzip(ret1);
System.out.println("还原之后大小:" + ret2.length); //写出文件
String writePath = System.getProperty("user.dir") + File.separatorChar + "receive" + File.separatorChar + "Netty+3.1中文用户手册.doc.jpg";
FileOutputStream fos = new FileOutputStream(writePath);
fos.write(ret2);
fos.close(); }
}

  

Request.java类

public class Request implements Serializable {

	/**
*
*/
private static final long serialVersionUID = 1L; private String id;
private String name;
private String requestMessage;
private byte[] attachment; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getRequestMessage() {
return requestMessage;
} public void setRequestMessage(String requestMessage) {
this.requestMessage = requestMessage;
} public byte[] getAttachment() {
return attachment;
} public void setAttachment(byte[] attachment) {
this.attachment = attachment;
} }

  

Response.java类

public class Response implements Serializable {

	/**
*
*/
private static final long serialVersionUID = 1L; private String id; private String name; private String responseMessage; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getResponseMessage() {
return responseMessage;
} public void setResponseMessage(String responseMessage) {
this.responseMessage = responseMessage;
} }

  

MarshallingCodeCFactory.java

序列号编码解码类

public final class MarshallingCodeCFactory {

	/**
* 解码器
* @return
*/
public static MarshallingDecoder buildMarshallingDecoder() {
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);
//构建MarshallingDecoder对象,两个参数分别为provider和消息序列化后的最大长度
MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024*1024*1);
return decoder; } /**
* 编码器
* @return
*/
public static MarshallingEncoder buildMarshallingEncoder() {
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);
//构建MarshallingEncoder对象,参数为provider;
MarshallingEncoder encoder = new MarshallingEncoder(provider);
return encoder; }
}

  

开始开发client,server功能

server.java

public class Server {

	public static void main(String[] args) throws InterruptedException {
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(boss, worker)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() { @Override
protected void initChannel(SocketChannel ch) throws Exception {
// TODO Auto-generated method stub
//设置编码解码
ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
ch.pipeline().addLast(new ServerHandler());
}
});
ChannelFuture cf = b.bind(8765).sync(); cf.channel().closeFuture().sync();
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}

  

serverHandler.java

需要继承ChannelHandlerAdapter类

public class ServerHandler extends ChannelHandlerAdapter {

	@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
//super.exceptionCaught(ctx, cause);
cause.printStackTrace();
ctx.close();
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
//super.channelRead(ctx, msg);
Request request = (Request) msg;
System.out.println("Server: " + request.getId() + ","+request.getName()+","+request.getRequestMessage()); //接收附件 写入文件
byte[] attachment = GzipUtils.ungzip(request.getAttachment());
String path = System.getProperty("user.dir") + File.separatorChar + "receive" + File.separatorChar + request.getId() +".png";
FileOutputStream outputStream = new FileOutputStream(path);
outputStream.write(attachment);
outputStream.close(); //返回数据
Response response = new Response();
response.setId(request.getId());
response.setName("response: " + request.getName());
response.setResponseMessage("相应的内容: " + request.getRequestMessage());
ctx.writeAndFlush(response); } }

  

client.java类

public class Client {

	public static void main(String[] args) throws Exception {

		EventLoopGroup worker = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(worker)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() { @Override
protected void initChannel(SocketChannel ch) throws Exception {
// TODO Auto-generated method stub
//设置编码解码
ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
ch.pipeline().addLast(new ClientHandler());
}
});
ChannelFuture cf = b.connect("127.0.0.1", 8765).sync(); for(int i=0; i< 5; i++) {
Request request = new Request();
request.setId(i + "");
request.setName( "pro"+ i);
request.setRequestMessage("数据信息Client~Server:" + i); //发送附件
String path = System.getProperty("user.dir") + File.separatorChar + "resources" + File.separatorChar + "1.png";
File file = new File(path);
FileInputStream inputStream = new FileInputStream(file);
byte[] data = new byte[inputStream.available()];
inputStream.read(data);
inputStream.close();
request.setAttachment(GzipUtils.gzip(data));
cf.channel().writeAndFlush(request);
} System.out.println("user.dir: " + System.getProperty("user.dir") + File.separatorChar + "resources" + File.separatorChar + "1.png" ); cf.channel().closeFuture().sync();
worker.shutdownGracefully();
} }

  

ClientHandler.java类

需要继承ChannelHandlerAdapter类

public class ClientHandler extends ChannelHandlerAdapter {

	@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
//super.exceptionCaught(ctx, cause);
cause.printStackTrace();
ctx.close();
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
//super.channelRead(ctx, msg);
try {
Response response = (Response) msg;
System.out.println("Client : " + response.getId() + ","+response.getName()+","+response.getResponseMessage());
} finally {
// TODO: handle finally clause
ReferenceCountUtil.release(msg);
} } }

  

目录如下:

netty: marshalling传递对象,传输附件GzipUtils的更多相关文章

  1. netty: 编解码之jboss marshalling, 用marshalling进行对象传输

    jboss marshalling是jboss内部的一个序列化框架,速度也十分快,这里netty也提供了支持,使用十分方便. TCP在网络通讯的时候,通常在解决TCP粘包.拆包问题的时候,一般会用以下 ...

  2. netty的对象传输

    pom <!-- https://mvnrepository.com/artifact/io.netty/netty-all --> <dependency> <grou ...

  3. Netty4.x中文教程系列(四) 对象传输

    Netty4.x中文教程系列(四)  对象传输 我们在使用netty的过程中肯定会遇到传输对象的情况,Netty4通过ObjectEncoder和ObjectDecoder来支持. 首先我们定义一个U ...

  4. Android 全局获取 Context 与使用 Intent 传递对象

    =====================全局获取 Context======================== Android 开发中很多地方需要用到 Context,比如弹出 Toast.启动活 ...

  5. Android--Intent传递对象

    Intent 传递对象通常有两种实现方式,Serializable 和 Parcelable: 一.Serializable:序列化,表示将一个对象转换成可存储或可传输的状态,序列化后的对象可以在网络 ...

  6. Intent传递对象——Serializable和Parcelable区别

    为什么要将对象序列化? 1.永久性保存对象,保存对象的字节序列到本地文件中: 2.用过序列化对象在网络中传递对象: 3.通过序列化对象在进程间传递对象. 1.实现Serializable接口 Seri ...

  7. 使用HttpURLConnection实现在android客户端和服务器之间传递对象

    一般情况下,客户端和服务端的数据交互都是使用json和XML,相比于XML,json更加轻量级,并且省流量,但是,无论我们用json还是用xml,都需要我们先将数据封装成json字符串或者是一个xml ...

  8. Android中的Parcel机制 实现Bundle传递对象

    Android中的Parcel机制    实现了Bundle传递对象    使用Bundle传递对象,首先要将其序列化,但是,在Android中要使用这种传递对象的方式需要用到Android Parc ...

  9. 为什么Intent传递对象的时候必须要将对象序列化呢?

    Intent可以算是四大组件之间的胶水,比如在Activity1与Activity2之间传递对象的时候,必须要将对象序列化, 可是为什么要将对象序列化呢? Intent在启动其他组件时,会离开当前应用 ...

随机推荐

  1. docker使用2

    新建并启动容器 docker  run  [options]  imageId options -i  以交互模式运行容器 -t  为容器重新分配一个为终端设备 -p  主机端口:容器端口 --nam ...

  2. 【LEETCODE】56、数组分类,适中级别,题目:62、63、1035

    package y2019.Algorithm.array.medium; /** * @ClassName UniquePathsWithObstacles * @Description TODO ...

  3. 在centos7.6上部署.netcore 3.0 web程序

    首先需要一个全新的centos系统. 第一步:按照微软官方文档配置.netcore环境: https://dotnet.microsoft.com/download/linux-package-man ...

  4. Arduino 计算机视觉系统概述

    计算机视觉系统概述 计算机视觉系统是最近比较热门的研究领域,今天开始给大家介绍下计算机视觉相关的知识. 视觉是人的所有感官中最敏感的一种,人的视觉可以感知环境,而机器的视觉却很难感知环境 为了解决计算 ...

  5. js 页面技巧

    需要获取页面上固定的某个按钮的属性值.我们需要在页面加载完的第一刻将值存储到定义的变量,防止用户更改页面样式读不出当前元素.如果页面刷新会重置当前属性 <body> <input v ...

  6. python-django框架中使用docker和elasticsearch配合实现搜索功能

    注意:系统环境为Ubuntu18 一.docker安装 0:如果之前有安装过docker使用以下命令卸载: sudo apt-get remove docker docker-engine docke ...

  7. JML规格编程系列——OO Unit3分析和总结

    本文是BUAA OO课程Unit3在课程讲授.三次作业完成.自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客.主要包含JML相关梳理.SMT Solver验证.JML单元 ...

  8. git下,输入git log 进入log 怎么退出

    解决方案: 英文状态下按Q就可以了 ctrl + c (应该是Linux命令中断的意思,很多中断都是这个命令). Paste_Image.png

  9. win10开启redis失败解决方案

    输入命令:redis-server redis.windows.conf 提示:解决redis无法启动,报错:无法将“redis-server”项识别为 cmdlet.函数.脚本文件或可运行程 序的名 ...

  10. Ubuntu恢复默认界面命令

    命令: dconf reset -f /