专栏首页xdecodeNetty之二进制文件传输

Netty之二进制文件传输

传输会话简要

客户端发起一个文本请求给服务器端, 服务器端解析里面文本, 返回文件给客户端, 客户端解析文件

服务器端

因为示例文件比较小, 所以没有做分段传输, 而是直接一次性把整个文件byte[]都发给客户端了.

如果需要传输大文件, 则需要做粘包拆包, 参考另外一篇博文 Netty之粘包分包

需要三个ChannelPipeline

1                             // 解析客户端发送的文本json
2                             pipeline.addLast(new StringDecoder());
3                             // 二进制文件加密传输
4                             pipeline.addLast(new ObjectEncoder());
5                             // 业务逻辑
6                             pipeline.addLast(new FileServerHandler());

FileServerHandler业务逻辑

            // 获取到客户端请求, 解析path, 返回二进制文件
            JSONObject jo = new JSONObject(msg.toString());
            if (StringUtils.isNotEmpty(jo.optString("path"))) {
                PDFContent pdf = new PDFContent();
                byte[] content = com.fr.general.IOUtils.inputStream2Bytes(new FileInputStream(jo.optString("path")));
                pdf.setContent(content);
                ctx.writeAndFlush(pdf);
            } else {
                System.out.println(jo.optString("res"));
            }

客户端

跟服务器端对应的三个ChannelPipeline

1                             // 传输文本给服务器端
2                             p.addLast(new StringEncoder());
3                             // 二进制文件获取解析
4                             p.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(this
5                                     .getClass().getClassLoader())));
6                             // 客户端业务代码
7                             p.addLast(new FileClientHandler());

FileClientHandler业务逻辑

 1         @Override
 2         public void channelActive(ChannelHandlerContext ctx) {
 3             try {
 4                 // 将要获取的pdf路径发送给服务器端
 5                 JSONObject jo = JSONObject.create().put("path", "d:\\a.pdf");
 6                 ctx.writeAndFlush(jo.toString());
 7             } catch (JSONException e) {
 8                 e.printStackTrace();
 9             }
10         }
11 
12         @Override
13         public void channelRead(ChannelHandlerContext ctx, Object msg) {
14             PDFContent content = (PDFContent) msg;
15             // 从服务器端获取的二进制文件存到本地
16             String fileName = UUID.randomUUID().toString() + ".pdf";
17             File file = new File("D:\\" + fileName);
18             try {
19                 FileOutputStream out = new FileOutputStream(file);
20                 IOUtils.copyBinaryTo(new ByteArrayInputStream(content.getContent()), out);
21                 out.close();
22             } catch (FileNotFoundException e) {
23                 e.printStackTrace();
24             } catch (IOException e) {
25                 e.printStackTrace();
26             }
27             try {
28                 JSONObject jo = JSONObject.create().put("res", "Thank You, I Have The File!");
29                 ctx.writeAndFlush(jo.toString());
30                 ctx.close();
31             } catch (JSONException e) {
32                 e.printStackTrace();
33             }
34         }

完整的代码如下

FileClient & FileClientHandler

  1 package test;
  2 
  3 import com.fr.general.IOUtils;
  4 import com.fr.json.JSONException;
  5 import com.fr.json.JSONObject;
  6 import com.fr.stable.core.UUID;
  7 import io.netty.bootstrap.Bootstrap;
  8 import io.netty.channel.ChannelFuture;
  9 import io.netty.channel.ChannelHandlerContext;
 10 import io.netty.channel.ChannelInboundHandlerAdapter;
 11 import io.netty.channel.ChannelInitializer;
 12 import io.netty.channel.ChannelPipeline;
 13 import io.netty.channel.EventLoopGroup;
 14 import io.netty.channel.nio.NioEventLoopGroup;
 15 import io.netty.channel.socket.SocketChannel;
 16 import io.netty.channel.socket.nio.NioSocketChannel;
 17 import io.netty.handler.codec.serialization.ClassResolvers;
 18 import io.netty.handler.codec.serialization.ObjectDecoder;
 19 import io.netty.handler.codec.string.StringEncoder;
 20 
 21 import java.io.ByteArrayInputStream;
 22 import java.io.File;
 23 import java.io.FileNotFoundException;
 24 import java.io.FileOutputStream;
 25 import java.io.IOException;
 26 
 27 public class FileClient {
 28 
 29     public FileClient(){
 30 
 31     }
 32 
 33     public void start() {
 34         EventLoopGroup group = new NioEventLoopGroup();
 35         try {
 36             Bootstrap bootstrap = new Bootstrap();
 37             bootstrap.group(group)
 38                     .channel(NioSocketChannel.class)
 39                     .handler(new ChannelInitializer<SocketChannel>() {
 40 
 41                         @Override
 42                         protected void initChannel(SocketChannel s) throws Exception {
 43                             ChannelPipeline p = s.pipeline();
 44                             // 传输文本给服务器端
 45                             p.addLast(new StringEncoder());
 46                             // 二进制文件获取解析
 47                             p.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(this
 48                                     .getClass().getClassLoader())));
 49                             // 客户端业务代码
 50                             p.addLast(new FileClientHandler());
 51                         }
 52                     });
 53             ChannelFuture future = bootstrap.connect("localhost", 7766).sync();
 54             future.channel().closeFuture().sync();
 55         } catch (InterruptedException e) {
 56             e.printStackTrace();
 57         } finally {
 58             group.shutdownGracefully();
 59         }
 60     }
 61 
 62     public static void main(String[] args) throws InterruptedException {
 63         new FileClient().start();
 64     }
 65 
 66     private static class FileClientHandler extends ChannelInboundHandlerAdapter {
 67 
 68 
 69         @Override
 70         public void channelActive(ChannelHandlerContext ctx) {
 71             try {
 72                 // 将要获取的pdf路径发送给服务器端
 73                 JSONObject jo = JSONObject.create().put("path", "d:\\a.pdf");
 74                 ctx.writeAndFlush(jo.toString());
 75             } catch (JSONException e) {
 76                 e.printStackTrace();
 77             }
 78         }
 79 
 80         @Override
 81         public void channelRead(ChannelHandlerContext ctx, Object msg) {
 82             PDFContent content = (PDFContent) msg;
 83             // 从服务器端获取的二进制文件存到本地
 84             String fileName = UUID.randomUUID().toString() + ".pdf";
 85             File file = new File("D:\\" + fileName);
 86             try {
 87                 FileOutputStream out = new FileOutputStream(file);
 88                 IOUtils.copyBinaryTo(new ByteArrayInputStream(content.getContent()), out);
 89                 out.close();
 90             } catch (FileNotFoundException e) {
 91                 e.printStackTrace();
 92             } catch (IOException e) {
 93                 e.printStackTrace();
 94             }
 95             try {
 96                 JSONObject jo = JSONObject.create().put("res", "Thank You, I Have The File!");
 97                 ctx.writeAndFlush(jo.toString());
 98                 ctx.close();
 99             } catch (JSONException e) {
100                 e.printStackTrace();
101             }
102         }
103 
104         @Override
105         public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
106             cause.printStackTrace();
107             ctx.close();
108         }
109     }
110 }

FileServer & FileServerHandler

 1 package test;
 2 
 3 import com.fr.json.JSONObject;
 4 import com.fr.stable.StringUtils;
 5 import io.netty.bootstrap.ServerBootstrap;
 6 import io.netty.channel.ChannelFuture;
 7 import io.netty.channel.ChannelHandlerContext;
 8 import io.netty.channel.ChannelInboundHandlerAdapter;
 9 import io.netty.channel.ChannelInitializer;
10 import io.netty.channel.ChannelOption;
11 import io.netty.channel.ChannelPipeline;
12 import io.netty.channel.EventLoopGroup;
13 import io.netty.channel.nio.NioEventLoopGroup;
14 import io.netty.channel.socket.SocketChannel;
15 import io.netty.channel.socket.nio.NioServerSocketChannel;
16 import io.netty.handler.codec.serialization.ObjectEncoder;
17 import io.netty.handler.codec.string.StringDecoder;
18 import io.netty.handler.logging.LogLevel;
19 import io.netty.handler.logging.LoggingHandler;
20 
21 import java.io.FileInputStream;
22 
23 public class FileServer {
24 
25     private FileServer() {
26         startServer();
27     }
28 
29     private void startServer() {
30         EventLoopGroup bossGroup = new NioEventLoopGroup(1);
31         EventLoopGroup workerGroup = new NioEventLoopGroup();
32         try{
33             ServerBootstrap bootstrap = new ServerBootstrap();
34             bootstrap.group(bossGroup, workerGroup)
35                     .channel(NioServerSocketChannel.class)
36                     .option(ChannelOption.SO_BACKLOG, 100)
37                     .handler(new LoggingHandler(LogLevel.INFO))
38                     .childHandler(new ChannelInitializer<SocketChannel>() {
39                         @Override
40                         protected void initChannel(SocketChannel ch) throws Exception {
41                             ChannelPipeline pipeline = ch.pipeline();
42                             // 解析客户端发送的文本json
43                             pipeline.addLast(new StringDecoder());
44                             // 二进制文件加密传输
45                             pipeline.addLast(new ObjectEncoder());
46                             // 业务逻辑
47                             pipeline.addLast(new FileServerHandler());
48                         }
49                     });
50             ChannelFuture future = bootstrap.bind("localhost", 7766).sync();
51             future.channel().closeFuture().sync();
52         } catch (InterruptedException e) {
53             e.printStackTrace();
54         } finally {
55             bossGroup.shutdownGracefully();
56             workerGroup.shutdownGracefully();
57         }
58 
59     }
60 
61     private class FileServerHandler extends ChannelInboundHandlerAdapter {
62 
63         @Override
64         public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
65             // 获取到客户端请求, 解析path, 返回二进制文件
66             JSONObject jo = new JSONObject(msg.toString());
67             if (StringUtils.isNotEmpty(jo.optString("path"))) {
68                 PDFContent pdf = new PDFContent();
69                 byte[] content = com.fr.general.IOUtils.inputStream2Bytes(new FileInputStream(jo.optString("path")));
70                 pdf.setContent(content);
71                 ctx.writeAndFlush(pdf);
72             } else {
73                 System.out.println(jo.optString("res"));
74             }
75         }
76 
77         @Override
78         public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
79             cause.printStackTrace();
80             ctx.close();
81         }
82     }
83 
84     public static void main(String[] args){
85         // 启动Server
86         new FileServer();
87     }
88 
89 
90 }

PDFContent

 1 package test;
 2 
 3 import java.io.Serializable;
 4 
 5 /**
 6  * 文件的封装
 7  */
 8 public class PDFContent implements Serializable{
 9 
10     private byte[] content;
11 
12     public byte[] getContent() {
13         return content;
14     }
15 
16     public void setContent(byte[] content) {
17         this.content = content;
18     }
19 }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring MVC核心技术

    目录 异常处理 类型转换器 数据验证 文件上传与下载 拦截器 ----  异常处理 Spring MVC中, 系统的DAO, Service, Controll...

    用户1216491
  • Java调用PDFBox打印自定义纸张PDF

    打印对象 一份设置为A3纸张, 页面边距为(10, 10, 10, 10)mm的PDF文件. ? PageFormat  默认PDFPrintable无法设置页...

    用户1216491
  • Spring之AOP

    之前在另外一篇博文里介绍过AOP的概念, 这边不在赘述, 可以参考 AOP与动态代理 本文主要介绍Spring中AOP的应用. 切入点: 具体实现类的方法 ...

    用户1216491
  • Netty之入门案例

      前面给大家介绍了NIO,我们会发现用NIO实现异步非阻塞的网络通信代码量非常大,而且并不是很好理解,在实际的开发中一般我们也都是会实现基于NIO的框架来操作...

    用户4919348
  • Netty入门(一)

    在文章开始之前首先明确一个问题,为什么要使用Netty,Netty解决了什么问题,围绕着这个问题我们开始本篇文章的学习

    tanoak
  • Netty的TCP粘包/拆包(源码二)

    假设客户端分别发送了两个数据包D1和D2给服务器,由于服务器端一次读取到的字节数是不确定的,所以可能发生四种情况:

    用户3003813
  • Netty入门HelloWorld

    今天下班之后无聊,学习了一下长链接的一款非常秀的框架——netty,netty在很多?java开发的中间件中都有很坚实的地位。于是,在下班之余我学习了一下这款优...

    奕仁
  • Netty(1):第一个netty程序

    为什么选择Netty   netty是业界最流行的NIO框架之一,它的健壮型,功能,性能,可定制性和可扩展性都是首屈一指的,Hadoop的RPC框架Avro就使...

    SecondWorld
  • java架构之路-(netty专题)netty的基本使用和netty聊天室

      上次博客,我们主要说了我们的IO模型,BIO同步阻塞,NIO同步非阻塞,AIO基于NIO二次封装的异步非阻塞,最重要的就是我们的NIO,脑海中应该有NIO的...

    小菜的不能再菜
  • Netty入门实例-Http服务

      启动服务器,返回在浏览器地址栏中输入 http://localhost:8666/index.html

    用户4919348

扫码关注云+社区

领取腾讯云代金券