zoukankan      html  css  js  c++  java
  • 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 }
    View Code

    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 }
    View Code

    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 }
    View Code
  • 相关阅读:
    HTML5 GeoLocation 地理定位
    HTML5 LocalStorage 本地存储
    JS-事件代理(委托)
    面向对象(封装、继承、多态)
    js图片预加载
    jQuery 事件
    svn无法验证
    Ext.data.Store(转)
    ExtJS实现Excel导出(转)
    <![CDATA[ ]]> 意思
  • 原文地址:https://www.cnblogs.com/xdecode/p/7978147.html
Copyright © 2011-2022 走看看