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. 《Redis Mysql 双写一致性问题》

    一:序 - 最近在对数据做缓存时候,会涉及到如何保证 数据库/Redis 一致性问题. - 刚好今天来总结下 一致性问题 产生的问题,和可能存在的解决方案. 二:(更新策略)-  先更新数据库,后更新 ...

  2. Windows的socket编程

    ################服务端 1.准备工作导入头文件 #include<WinSock2.h> #pragma comment(lib, "ws2_32.lib&quo ...

  3. WITH AS学习

    一.WITH AS的含义     WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到.有的时候, ...

  4. Spring Cloud--实现Eureka的高可用(Eureka集群搭建)实例

    将10086注册到10087上: 再在10086服务的基础上复制一个Eureka的服务,端口为10087,将其注册到10086上: application-name的名称保持一致,只是一个服务的两个实 ...

  5. ArcGIS 字段计算器 Python 坑

    最近要处理个简单数据,一个字段中为文本类型,包含各种描述.要求是包含平方米的数值提取出来,变成数值,如果包含多个,则把各个值累加起来. 比如 字段值为 “非法占用100平方米” 处理后结果为 100 ...

  6. 终于明白六大类UML类图关系了

    UML,全称Unified Modeling Language,统一建模语言.而UML图分为用例图.类图.对象图.状态图.活动图.时序图.协作图.构件图.部署图等9种图. 在面向对象语言中,我们经常看 ...

  7. 【SQL Server数据迁移】32位的机器:SQL Server中查询ORACLE的数据

    从SQL Server中查询ORACLE中的数据,可以在SQL Server中创建到ORACLE的链接服务器来实现的,但是根据32位 .64位的机器和软件,需要用不同的驱动程序来实现. 在32位的机器 ...

  8. WPF内嵌网页的两种方式

    在wpf程序中,有时会内嵌网页.内嵌网页有两种方法,一种是使用wpf自带WebBrowser控件来调用IE内核,另一种是使用CefSharp包来调用chrom内核. 一.第一种使用自带WebBrows ...

  9. AES不同语言加密解密

    AES加密模式和填充方式:还有其他 算法/模式/填充 16字节加密后数据长度 不满16字节加密后长度 AES/CBC/NoPadding 16 不支持 AES/CBC/PKCS5Padding 32 ...

  10. springboot打成jar包后无法解压

    springboot打成jar包后无法解压 Springboot打出来的jar,用压缩工具解压报错.Why? 先说解决办法. 1.解决办法 executable属性导致的,属性改成false后重新打包 ...