背景

作为网络传输框架,免不了哟啊传输对象,对象在传输之前就要序列化,这个序列化的过程就是编码过程。接收到编码后的数据就需要解码,还原传输的数据。

代码

工厂类

  1. import io.netty.handler.codec.marshalling.DefaultMarshallerProvider;
  2. import io.netty.handler.codec.marshalling.DefaultUnmarshallerProvider;
  3. import io.netty.handler.codec.marshalling.MarshallerProvider;
  4. import io.netty.handler.codec.marshalling.MarshallingDecoder;
  5. import io.netty.handler.codec.marshalling.MarshallingEncoder;
  6. import io.netty.handler.codec.marshalling.UnmarshallerProvider;
  7.  
  8. import org.jboss.marshalling.MarshallerFactory;
  9. import org.jboss.marshalling.Marshalling;
  10. import org.jboss.marshalling.MarshallingConfiguration;
  11.  
  12. /**
  13. * Marshalling工厂
  14. * @author(alienware)
  15. * @since 2014-12-16
  16. */
  17. public final class MarshallingCodeCFactory {
  18.  
  19. /**
  20. * 创建Jboss Marshalling解码器MarshallingDecoder
  21. * @return MarshallingDecoder
  22. */
  23. public static MarshallingDecoder buildMarshallingDecoder() {
  24. //首先通过Marshalling工具类的精通方法获取Marshalling实例对象 参数serial标识创建的是java序列化工厂对象。
  25. final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
  26. //创建了MarshallingConfiguration对象,配置了版本号为5
  27. final MarshallingConfiguration configuration = new MarshallingConfiguration();
  28. configuration.setVersion(5);
  29. //根据marshallerFactory和configuration创建provider
  30. UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);
  31. //构建Netty的MarshallingDecoder对象,俩个参数分别为provider和单个消息序列化后的最大长度
  32. MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024 * 1024 * 1);
  33. return decoder;
  34. }
  35.  
  36. /**
  37. * 创建Jboss Marshalling编码器MarshallingEncoder
  38. * @return MarshallingEncoder
  39. */
  40. public static MarshallingEncoder buildMarshallingEncoder() {
  41. final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
  42. final MarshallingConfiguration configuration = new MarshallingConfiguration();
  43. configuration.setVersion(5);
  44. MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);
  45. //构建Netty的MarshallingEncoder对象,MarshallingEncoder用于实现序列化接口的POJO对象序列化为二进制数组
  46. MarshallingEncoder encoder = new MarshallingEncoder(provider);
  47. return encoder;
  48. }
  49. }

服务器端

  1. import io.netty.bootstrap.ServerBootstrap;
  2. import io.netty.channel.ChannelFuture;
  3. import io.netty.channel.ChannelInitializer;
  4. import io.netty.channel.ChannelOption;
  5. import io.netty.channel.EventLoopGroup;
  6. import io.netty.channel.nio.NioEventLoopGroup;
  7. import io.netty.channel.socket.SocketChannel;
  8. import io.netty.channel.socket.nio.NioServerSocketChannel;
  9. import io.netty.handler.logging.LogLevel;
  10. import io.netty.handler.logging.LoggingHandler;
  11.  
  12. public class Server {
  13.  
  14. public static void main(String[] args) throws Exception{
  15.  
  16. EventLoopGroup pGroup = new NioEventLoopGroup();
  17. EventLoopGroup cGroup = new NioEventLoopGroup();
  18.  
  19. ServerBootstrap b = new ServerBootstrap();
  20. b.group(pGroup, cGroup)
  21. .channel(NioServerSocketChannel.class)
  22. .option(ChannelOption.SO_BACKLOG, 1024)
  23. //设置日志
  24. .handler(new LoggingHandler(LogLevel.INFO))
  25. .childHandler(new ChannelInitializer<SocketChannel>() {
  26. protected void initChannel(SocketChannel sc) throws Exception {
  27. sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
  28. sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
  29. sc.pipeline().addLast(new ServerHandler());
  30. }
  31. });
  32.  
  33. ChannelFuture cf = b.bind(8765).sync();
  34.  
  35. cf.channel().closeFuture().sync();
  36. pGroup.shutdownGracefully();
  37. cGroup.shutdownGracefully();
  38.  
  39. }
  40. }
  1. import io.netty.channel.ChannelHandlerAdapter;
  2. import io.netty.channel.ChannelHandlerContext;
  3.  
  4. import java.io.File;
  5. import java.io.FileOutputStream;
  6.  
  7. import bhz.utils.GzipUtils;
  8.  
  9. public class ServerHandler extends ChannelHandlerAdapter{
  10.  
  11. @Override
  12. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  13.  
  14. }
  15.  
  16. @Override
  17. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  18. Req req = (Req)msg;
  19. System.out.println("Server : " + req.getId() + ", " + req.getName() + ", " + req.getRequestMessage());
  20. byte[] attachment = GzipUtils.ungzip(req.getAttachment());
  21.  
  22. String path = System.getProperty("user.dir") + File.separatorChar + "receive" + File.separatorChar + "001.jpg";
  23. FileOutputStream fos = new FileOutputStream(path);
  24. fos.write(attachment);
  25. fos.close();
  26.  
  27. Resp resp = new Resp();
  28. resp.setId(req.getId());
  29. resp.setName("resp" + req.getId());
  30. resp.setResponseMessage("响应内容" + req.getId());
  31. ctx.writeAndFlush(resp);//.addListener(ChannelFutureListener.CLOSE);
  32. }
  33.  
  34. @Override
  35. public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
  36.  
  37. }
  38.  
  39. @Override
  40. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  41. ctx.close();
  42. }
  43.  
  44. }

客户端

  1. import io.netty.bootstrap.Bootstrap;
  2. import io.netty.channel.ChannelFuture;
  3. import io.netty.channel.ChannelInitializer;
  4. import io.netty.channel.EventLoopGroup;
  5. import io.netty.channel.nio.NioEventLoopGroup;
  6. import io.netty.channel.socket.SocketChannel;
  7. import io.netty.channel.socket.nio.NioSocketChannel;
  8.  
  9. import java.io.File;
  10. import java.io.FileInputStream;
  11.  
  12. import bhz.utils.GzipUtils;
  13.  
  14. public class Client {
  15.  
  16. public static void main(String[] args) throws Exception{
  17.  
  18. EventLoopGroup group = new NioEventLoopGroup();
  19. Bootstrap b = new Bootstrap();
  20. b.group(group)
  21. .channel(NioSocketChannel.class)
  22. .handler(new ChannelInitializer<SocketChannel>() {
  23. @Override
  24. protected void initChannel(SocketChannel sc) throws Exception {
  25. sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
  26. sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
  27. sc.pipeline().addLast(new ClientHandler());
  28. }
  29. });
  30.  
  31. ChannelFuture cf = b.connect("127.0.0.1", 8765).sync();
  32.  
  33. for(int i = 0; i < 5; i++ ){
  34. Req req = new Req();
  35. req.setId("" + i);
  36. req.setName("pro" + i);
  37. req.setRequestMessage("数据信息" + i);
  38. String path = System.getProperty("user.dir") + File.separatorChar + "sources" + File.separatorChar + "001.jpg";
  39. File file = new File(path);
  40. FileInputStream in = new FileInputStream(file);
  41. byte[] data = new byte[in.available()];
  42. in.read(data);
  43. in.close();
  44. req.setAttachment(GzipUtils.gzip(data));
  45. cf.channel().writeAndFlush(req);
  46. }
  47.  
  48. cf.channel().closeFuture().sync();
  49. group.shutdownGracefully();
  50. }
  51. }
  1. import io.netty.channel.ChannelHandlerAdapter;
  2. import io.netty.channel.ChannelHandlerContext;
  3. import io.netty.util.ReferenceCountUtil;
  4.  
  5. public class ClientHandler extends ChannelHandlerAdapter{
  6.  
  7. @Override
  8. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  9.  
  10. }
  11.  
  12. @Override
  13. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  14. try {
  15. Resp resp = (Resp)msg;
  16. System.out.println("Client : " + resp.getId() + ", " + resp.getName() + ", " + resp.getResponseMessage());
  17. } finally {
  18. ReferenceCountUtil.release(msg);
  19. }
  20. }
  21.  
  22. @Override
  23. public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
  24.  
  25. }
  26.  
  27. @Override
  28. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  29. ctx.close();
  30. }
  31.  
  32. }

工具类(压缩文件)

  1. import java.io.ByteArrayInputStream;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.FileOutputStream;
  6. import java.util.zip.GZIPInputStream;
  7. import java.util.zip.GZIPOutputStream;
  8.  
  9. public class GzipUtils {
  10.  
  11. public static byte[] gzip(byte[] data) throws Exception{
  12. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  13. GZIPOutputStream gzip = new GZIPOutputStream(bos);
  14. gzip.write(data);
  15. gzip.finish();
  16. gzip.close();
  17. byte[] ret = bos.toByteArray();
  18. bos.close();
  19. return ret;
  20. }
  21.  
  22. public static byte[] ungzip(byte[] data) throws Exception{
  23. ByteArrayInputStream bis = new ByteArrayInputStream(data);
  24. GZIPInputStream gzip = new GZIPInputStream(bis);
  25. byte[] buf = new byte[1024];
  26. int num = -1;
  27. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  28. while((num = gzip.read(buf, 0 , buf.length)) != -1 ){
  29. bos.write(buf, 0, num);
  30. }
  31. gzip.close();
  32. bis.close();
  33. byte[] ret = bos.toByteArray();
  34. bos.flush();
  35. bos.close();
  36. return ret;
  37. }
  38.  
  39. public static void main(String[] args) throws Exception{
  40.  
  41. //读取文件
  42. String readPath = System.getProperty("user.dir") + File.separatorChar + "sources" + File.separatorChar + "006.jpg";
  43. File file = new File(readPath);
  44. FileInputStream in = new FileInputStream(file);
  45. byte[] data = new byte[in.available()];
  46. in.read(data);
  47. in.close();
  48.  
  49. System.out.println("文件原始大小:" + data.length);
  50. //测试压缩
  51.  
  52. byte[] ret1 = GzipUtils.gzip(data);
  53. System.out.println("压缩之后大小:" + ret1.length);
  54.  
  55. byte[] ret2 = GzipUtils.ungzip(ret1);
  56. System.out.println("还原之后大小:" + ret2.length);
  57.  
  58. //写出文件
  59. String writePath = System.getProperty("user.dir") + File.separatorChar + "receive" + File.separatorChar + "006.jpg";
  60. FileOutputStream fos = new FileOutputStream(writePath);
  61. fos.write(ret2);
  62. fos.close();
  63.  
  64. }
  65.  
  66. }

数据对象

  1. import java.io.Serializable;
  2.  
  3. public class Req implements Serializable{
  4.  
  5. private static final long SerialVersionUID = 1L;
  6.  
  7. private String id ;
  8. private String name ;
  9. private String requestMessage ;
  10. private byte[] attachment;
  11.  
  12. public String getId() {
  13. return id;
  14. }
  15. public void setId(String id) {
  16. this.id = id;
  17. }
  18. public String getName() {
  19. return name;
  20. }
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. public String getRequestMessage() {
  25. return requestMessage;
  26. }
  27. public void setRequestMessage(String requestMessage) {
  28. this.requestMessage = requestMessage;
  29. }
  30. public byte[] getAttachment() {
  31. return attachment;
  32. }
  33. public void setAttachment(byte[] attachment) {
  34. this.attachment = attachment;
  35. }
  36.  
  37. }
  1. import java.io.Serializable;
  2.  
  3. public class Resp implements Serializable{
  4.  
  5. private static final long serialVersionUID = 1L;
  6.  
  7. private String id;
  8. private String name;
  9. private String responseMessage;
  10.  
  11. public String getId() {
  12. return id;
  13. }
  14. public void setId(String id) {
  15. this.id = id;
  16. }
  17. public String getName() {
  18. return name;
  19. }
  20. public void setName(String name) {
  21. this.name = name;
  22. }
  23. public String getResponseMessage() {
  24. return responseMessage;
  25. }
  26. public void setResponseMessage(String responseMessage) {
  27. this.responseMessage = responseMessage;
  28. }
  29.  
  30. }

架构师养成记--21.netty编码解码的更多相关文章

  1. 架构师养成记--20.netty的tcp拆包粘包问题

    问题描述 比如要发ABC DEFG HIJK 这一串数据,其中ABC是一个包,DEFG是一个包,HIJK是一个包.由于TCP是基于流发送的,所以有可能出现ABCD EFGH 这种情况,那么ABC和D就 ...

  2. 架构师养成记--19.netty

    一.Netty初步 为什么选择Netty? 和NIO比较,要实现一个通信要简单得很多,性能很好.分布式消息中间件.storm.Dubble都是使用Netty作为底层通信. Netty5.0要求jdk1 ...

  3. 架构师养成记--22.客户端与服务器端保持连接的解决方案,netty的ReadTimeoutHandler

    概述 保持客户端与服务器端连接的方案常用的有3种 1.长连接,也就是客户端与服务器端一直保持连接,适用于客户端比较少的情况. 2.定时段连接,比如在某一天的凌晨建立连接,适用于对实时性要求不高的情况. ...

  4. 架构师养成记--3.synchronized细节问题

    一.synchronized有锁重入的特点,某个线程得到对象的锁后,再次请求此对象可以再次得到改对象的锁.如下示例,在method1中调用method2,在method2中调用method3,而met ...

  5. 架构师养成记--35.redis集群搭建

    前记:redis哨兵经验之谈.哨兵做主从切换可能要花费一两秒,这一两秒可能会丢失很多数据.解决方法之一是在java代码中做控制,try catch 到 链接断开的异常就sleep 一两秒钟再conti ...

  6. 架构师养成记--15.Disruptor并发框架

    一.概述 disruptor对于处理并发任务很擅长,曾有人测过,一个线程里1s内可以处理六百万个订单,性能相当感人. 这个框架的结构大概是:数据生产端 --> 缓存 --> 消费端 缓存中 ...

  7. 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock

    ReentrantLock 有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级. this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决 ...

  8. 架构师养成记--12.Concurrent工具类CyclicBarrier和CountDownLatch

    java.util.concurrent.CyclicBarrier 一组线程共同等待,直到达到一个公共屏障点. 举个栗子,百米赛跑中,所有运动员都要等其他运动员都准备好后才能一起跑(假如没有发令员) ...

  9. 架构师养成记--11.Executor概述

    常用方法 Executors.newFiexdPool(int nThreads);固定线程数量的线程池: Executors.newSingleThreadExecutor();单个线程的线程池: ...

随机推荐

  1. 自己动手搭建Git服务器-Gitblit

      首先到官网http://gitblit.com/下载最新版本的Gitblit GO 解压缩到本地目录中 E:\git\gitblit132 官方文档:http://gitblit.com/setu ...

  2. Linux汇编与C互相调用

    一.简介 C语言调用汇编有两种方式:1.通过内嵌汇编  2.通过编译链接. 二.基础知识 对于C和汇编语言的接口主要有两个问题需要解决 1.调用者与被调用者的参数传递 正常的,定义一个函数总是希望它完 ...

  3. [Training Video - 4] [Groovy] String Functions

    def x="I like to read books before bed" def temp = x.split(" ") log.info "S ...

  4. spring mvc 数据回显

    1.spring mvc自动将传入的pojo数据存入request域 request中的key是该pojo类名,首字母小写. JSP controller 第一次访问user.jsp 填写表单 点击提 ...

  5. 团体程序设计天梯赛L1-017 到底有多二 2017-03-22 17:31 155人阅读 评论(0) 收藏

    L1-017. 到底有多二 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 一个整数"犯二的程度"定义为该数 ...

  6. C++ 的Tool工具收集

    C++ 的Tool工具收集 1. muparser - Fast Math Parser Library 数学公式解析函数,开源工具库 网址: http://muparser.beltoforion. ...

  7. shell 脚本 随机抽取班上学生

    #!/bin/bash # jw=('王浩' '谢云生' '黄科杨' '何星宇' '张宸兵' '邓培林' '刘桃' '杨沛东' '楚齐文' '咸鱼' '杨东' '>黄庭辉' '郑少文' '师靖' ...

  8. Mirth Connect的简单使用

    第一步: 切换到Channels界面,右键点击New Channel 第二步 : 上面是设置一些通道信息. 其中summary(概要) 界面主要包含 通道名称,数据类型,依赖,通道初始状态,附件(是否 ...

  9. Homework 4

    Homework 4 开发工具:dev c++ 开发语言:c++ 源代码上传至github:上传一直失败... 合作人:曹权 博客地址:http://www.cnblogs.com/c2016/ 这里 ...

  10. linux inode cheat sheet

    sector:扇区,硬盘存储的最小单位,大小为0.5KB(512字节) block:块文件存取的最小单位,1 block=8 sector,大小4KB inode:存储文件元信息.内容包括 * 文件的 ...