架构师养成记--21.netty编码解码
背景
作为网络传输框架,免不了哟啊传输对象,对象在传输之前就要序列化,这个序列化的过程就是编码过程。接收到编码后的数据就需要解码,还原传输的数据。
代码
工厂类
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; import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration; /**
* Marshalling工厂
* @author(alienware)
* @since 2014-12-16
*/
public final class MarshallingCodeCFactory { /**
* 创建Jboss Marshalling解码器MarshallingDecoder
* @return MarshallingDecoder
*/
public static MarshallingDecoder buildMarshallingDecoder() {
//首先通过Marshalling工具类的精通方法获取Marshalling实例对象 参数serial标识创建的是java序列化工厂对象。
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
//创建了MarshallingConfiguration对象,配置了版本号为5
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
//根据marshallerFactory和configuration创建provider
UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);
//构建Netty的MarshallingDecoder对象,俩个参数分别为provider和单个消息序列化后的最大长度
MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024 * 1024 * 1);
return decoder;
} /**
* 创建Jboss 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);
//构建Netty的MarshallingEncoder对象,MarshallingEncoder用于实现序列化接口的POJO对象序列化为二进制数组
MarshallingEncoder encoder = new MarshallingEncoder(provider);
return encoder;
}
}
服务器端
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{ EventLoopGroup pGroup = new NioEventLoopGroup();
EventLoopGroup cGroup = new NioEventLoopGroup(); ServerBootstrap b = new ServerBootstrap();
b.group(pGroup, cGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
//设置日志
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel sc) throws Exception {
sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
sc.pipeline().addLast(new ServerHandler());
}
}); ChannelFuture cf = b.bind(8765).sync(); cf.channel().closeFuture().sync();
pGroup.shutdownGracefully();
cGroup.shutdownGracefully(); }
}
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext; import java.io.File;
import java.io.FileOutputStream; import bhz.utils.GzipUtils; public class ServerHandler extends ChannelHandlerAdapter{ @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception { } @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Req req = (Req)msg;
System.out.println("Server : " + req.getId() + ", " + req.getName() + ", " + req.getRequestMessage());
byte[] attachment = GzipUtils.ungzip(req.getAttachment()); String path = System.getProperty("user.dir") + File.separatorChar + "receive" + File.separatorChar + "001.jpg";
FileOutputStream fos = new FileOutputStream(path);
fos.write(attachment);
fos.close(); Resp resp = new Resp();
resp.setId(req.getId());
resp.setName("resp" + req.getId());
resp.setResponseMessage("响应内容" + req.getId());
ctx.writeAndFlush(resp);//.addListener(ChannelFutureListener.CLOSE);
} @Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { } @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
} }
客户端
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; import java.io.File;
import java.io.FileInputStream; import bhz.utils.GzipUtils; public class Client { public static void main(String[] args) throws Exception{ EventLoopGroup group = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
sc.pipeline().addLast(new ClientHandler());
}
}); ChannelFuture cf = b.connect("127.0.0.1", 8765).sync(); for(int i = 0; i < 5; i++ ){
Req req = new Req();
req.setId("" + i);
req.setName("pro" + i);
req.setRequestMessage("数据信息" + i);
String path = System.getProperty("user.dir") + File.separatorChar + "sources" + File.separatorChar + "001.jpg";
File file = new File(path);
FileInputStream in = new FileInputStream(file);
byte[] data = new byte[in.available()];
in.read(data);
in.close();
req.setAttachment(GzipUtils.gzip(data));
cf.channel().writeAndFlush(req);
} cf.channel().closeFuture().sync();
group.shutdownGracefully();
}
}
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil; public class ClientHandler extends ChannelHandlerAdapter{ @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception { } @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
Resp resp = (Resp)msg;
System.out.println("Client : " + resp.getId() + ", " + resp.getName() + ", " + resp.getResponseMessage());
} finally {
ReferenceCountUtil.release(msg);
}
} @Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { } @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
} }
工具类(压缩文件)
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 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 + "006.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 + "006.jpg";
FileOutputStream fos = new FileOutputStream(writePath);
fos.write(ret2);
fos.close(); } }
数据对象
import java.io.Serializable;
public class Req 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;
}
}
import java.io.Serializable;
public class Resp 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;
}
}
架构师养成记--21.netty编码解码的更多相关文章
- 架构师养成记--20.netty的tcp拆包粘包问题
问题描述 比如要发ABC DEFG HIJK 这一串数据,其中ABC是一个包,DEFG是一个包,HIJK是一个包.由于TCP是基于流发送的,所以有可能出现ABCD EFGH 这种情况,那么ABC和D就 ...
- 架构师养成记--19.netty
一.Netty初步 为什么选择Netty? 和NIO比较,要实现一个通信要简单得很多,性能很好.分布式消息中间件.storm.Dubble都是使用Netty作为底层通信. Netty5.0要求jdk1 ...
- 架构师养成记--22.客户端与服务器端保持连接的解决方案,netty的ReadTimeoutHandler
概述 保持客户端与服务器端连接的方案常用的有3种 1.长连接,也就是客户端与服务器端一直保持连接,适用于客户端比较少的情况. 2.定时段连接,比如在某一天的凌晨建立连接,适用于对实时性要求不高的情况. ...
- 架构师养成记--3.synchronized细节问题
一.synchronized有锁重入的特点,某个线程得到对象的锁后,再次请求此对象可以再次得到改对象的锁.如下示例,在method1中调用method2,在method2中调用method3,而met ...
- 架构师养成记--35.redis集群搭建
前记:redis哨兵经验之谈.哨兵做主从切换可能要花费一两秒,这一两秒可能会丢失很多数据.解决方法之一是在java代码中做控制,try catch 到 链接断开的异常就sleep 一两秒钟再conti ...
- 架构师养成记--15.Disruptor并发框架
一.概述 disruptor对于处理并发任务很擅长,曾有人测过,一个线程里1s内可以处理六百万个订单,性能相当感人. 这个框架的结构大概是:数据生产端 --> 缓存 --> 消费端 缓存中 ...
- 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock
ReentrantLock 有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级. this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决 ...
- 架构师养成记--12.Concurrent工具类CyclicBarrier和CountDownLatch
java.util.concurrent.CyclicBarrier 一组线程共同等待,直到达到一个公共屏障点. 举个栗子,百米赛跑中,所有运动员都要等其他运动员都准备好后才能一起跑(假如没有发令员) ...
- 架构师养成记--11.Executor概述
常用方法 Executors.newFiexdPool(int nThreads);固定线程数量的线程池: Executors.newSingleThreadExecutor();单个线程的线程池: ...
随机推荐
- Vue.js基础知识
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml&q ...
- 安装scrapy解决的坑
在windows下: pip install scrapy 最后一步报错: 本来以为是缺少 Microsoft Visual C++ 14.0 这个库,一看下载需要400多M,算了再看下报错... 感 ...
- WSTMart开发文档
WSTMart开发文档页面 PC版 开源版 授权版 序言 WSTMart安装协议 WSTMart电商系统安装 商城前台安装操作指南 用户中心指南 商家中心操作指南 ...
- Python服务器开发 -- 网络基础-乾颐堂
网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. HTTP是高层协议,而TCP/IP是个协议集,包过许多的子协议.包括:传输层的 FTP,UDP,TCP协议等,网络层的ip ...
- std::time(0)找不到
http://zh.cppreference.com/w/cpp/chrono/c/time #include <ctime> isnan找不到 http://en.cppreferenc ...
- c# windows服务的制作
一.创建一个Windows Service )创建Windows Service项目 )对Service重命名 将Service1重命名为你服务名称,这里我们命名为Servicetest. 二.创建服 ...
- 一起做RGB-D SLAM(8) (关于调试与补充内容)
“一起做”系列完结后,我收到不少同学给我的反馈.他们提了一些在程序编译/运行过程中的问题.我把它们汇总起来,组成了这个“补充篇”.你也可以看成是一个Q&A. Q: OpenCV的版本?A: 我 ...
- unittest单元测试框架之coverage代码覆盖率统计
什么是coveage? coverage是一个检测单元测试覆盖率的工具,即检查你的测试用例是否覆盖到了所有的代码.当你通过pip install coverage成功安装完coverage后,就会在p ...
- SVN下的文件被locked不能update和commit
一次早上开机svn更新代码,提示某一个文件夹被locked,提示clean up,但是clearn up也不行,get lock不行,release lock不行 根据网上搜的,.svn(隐藏文件夹) ...
- AngularJS-$scope类
一.$scope的作用 用来在controller和view中进行数据.事件的传递 二.$scope和$rootscope的区别 1.$rootscope根作用域 2.$rootscope可以实现多个 ...