网络传输序列化框架(Netty+JBossMarshalling)

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

附下载链接

1,jboss-marshalling-1.3.0.CR9.jar

2,jboss-marshalling-serial-1.3.0.CR9.jar

 demo目录

解压缩类:GZipUtils.java

package bhz.netty.serial;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class GZipUtils {
	
	
	public static byte[] gzip(byte[] data) throws Exception{
		
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
		gzipOutputStream.write(data);
		gzipOutputStream.finish();
		gzipOutputStream.close();
		byte[] ret = byteArrayOutputStream.toByteArray();
		byteArrayOutputStream.close();
		return ret;
	}

	public static byte[] ungzip(byte[] data) throws Exception{
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
		GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream);
		byte[] buf = new byte[1024];
		int num = -1;
		ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
		while((num = gzipInputStream.read(buf,0,buf.length)) != -1) {
			byteOutputStream.write(buf,0,num);
		}
		gzipInputStream.close();
		byteArrayInputStream.close();
		byte[] ret = byteOutputStream.toByteArray();
		byteOutputStream.flush();
		byteOutputStream.close();
		return ret;
	}
	
	public static void main(String[] arg0) throws Exception{
		
		String readPath = System.getProperty("user.dir")+File.separatorChar+"sources"+File.separatorChar+"001.png";
		File file = new File(readPath);
		FileInputStream inputStream = new FileInputStream(file);
		byte[] data = new byte[inputStream.available()];
		inputStream.read(data);
		inputStream.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+"001.png";
		FileOutputStream outputStream = new FileOutputStream(writePath);
		outputStream.write(ret2);
		outputStream.close();
	}
}

客户端发送给服务端的请求对象Request

package bhz.netty.serial;

import java.io.Serializable;

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

package bhz.netty.serial;

import java.io.Serializable;

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;
	}
	
}

Marshalling框架编解码类MarshallingCodeCFactory.java

package bhz.netty.serial;

import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration;

import io.netty.handler.codec.marshalling.DefaultMarshallerProvider;
import io.netty.handler.codec.marshalling.DefaultUnmarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallingDecoder;
import io.netty.handler.codec.marshalling.MarshallingEncoder;
import io.netty.handler.codec.marshalling.UnmarshallerProvider;

public final class MarshallingCodeCFactory {

	/*
	 * 创建JBoss Marshalling解码器MarshallingDecoder
	 * @return MarshallingDecoder
	 * */
	
	public static MarshallingDecoder buildMarshallingDecoder() {
		
		final MarshallerFactory marshallingFactory = Marshalling.getProvidedMarshallerFactory("serial");
		
		final MarshallingConfiguration configuration = new MarshallingConfiguration();
		configuration.setVersion(5);
		UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallingFactory, configuration);
		//构件Netty的marshallingDecoder对象,两个参数分别为Provider和单个消息序列化后的最大长度
		MarshallingDecoder decoder = new MarshallingDecoder(provider,1024*1024*1);
		
		return decoder;
	}
	/*
	 * 创建Marshalling解码器 MarshallingEncoder
	 * return MarshallingEncoder
	 * */
	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 encoder = new MarshallingEncoder(provider);
		return encoder;
		
	}
	
}

服务端Server

package bhz.netty.serial;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class Server {

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		
		EventLoopGroup boss = new NioEventLoopGroup();
		EventLoopGroup worker = new NioEventLoopGroup();
		
		ServerBootstrap bootstrap = new ServerBootstrap();
		
		bootstrap.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 sc) throws Exception {
						// TODO Auto-generated method stub
						
						sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
						sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
						sc.pipeline().addLast(new ServerHandler());
					}
				});
		ChannelFuture channelFuture = bootstrap.bind(8888).sync();
		channelFuture.channel().closeFuture().sync();
		boss.shutdownGracefully();
		worker.shutdownGracefully();
	}

}

服务端处理方法ServerHandler.java

package bhz.netty.serial;

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

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class ServerHandler extends SimpleChannelInboundHandler {

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
		// TODO Auto-generated method stub
		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+"001.png";
		FileOutputStream fileOutputStream = new FileOutputStream(path);
		fileOutputStream.write(attachment);
		fileOutputStream.close();
		
		Response response = new Response();
		response.setId(request.getId());
		response.setName("response : "+request.getId());
		response.setResponseMessage("相应内容 : "+request.getId());
		ctx.writeAndFlush(response);
		
	}
}

客户端Client

package bhz.netty.serial;

import java.io.File;
import java.io.FileInputStream;

import io.netty.bootstrap.Bootstrap;
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;

public class Client {

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		EventLoopGroup worker = new NioEventLoopGroup();
		
		Bootstrap bootstrap = new Bootstrap();
		
		bootstrap.group(worker)
				 .channel(NioSocketChannel.class)
				 .handler(new ChannelInitializer<SocketChannel>() {

					@Override
					protected void initChannel(SocketChannel sc) throws Exception {
						// TODO Auto-generated method stub
						sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
						sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
						sc.pipeline().addLast(new ClientHandle());
					}
				});
		ChannelFuture channelFuture = bootstrap.connect("127.0.0.1",8888).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 + "sources" + File.separatorChar + "001.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));
			
			channelFuture.channel().writeAndFlush(request);
		}
		
		channelFuture.channel().closeFuture().sync();
		worker.shutdownGracefully();
	}

}

客户端处理类

package bhz.netty.serial;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class ClientHandle extends SimpleChannelInboundHandler{

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
		// TODO Auto-generated method stub
		Response response = (Response)msg;
		System.out.println("Client :" + response.getId()+" , "+response.getName()+" , "+response.getResponseMessage());

	}
}

运行结果

注意:先启动服务端,在启动客户端

 

 结论:

可以看出,这里实现了客户端与服务端进行了对象的传输,不再是简单的String对象的传输,并进行了图片的编辑码处理(其他文件同理)。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我要出家当道士

打赏是不可能,这辈子都不可能

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值