传输会话简要
客户端发起一个文本请求给服务器端, 服务器端解析里面文本, 返回文件给客户端, 客户端解析文件
服务器端
因为示例文件比较小, 所以没有做分段传输, 而是直接一次性把整个文件byte[]都发给客户端了.
如果需要传输大文件, 则需要做粘包拆包, 参考另外一篇博文 Netty之粘包分包
需要三个ChannelPipeline
1 ????????????????????????????// 解析客户端发送的文本json2 ????????????????????????????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(this5 ????????????????????????????????????.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 ????????@Override13 ????????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 ????????@Override105 ????????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 ????????????????????????@Override40 ????????????????????????protected void initChannel(SocketChannel ch) throws Exception {41 ????????????????????????????ChannelPipeline pipeline = ch.pipeline();42 ????????????????????????????// 解析客户端发送的文本json43 ????????????????????????????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 ????????@Override64 ????????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 ????????@Override78 ????????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 ????????// 启动Server86 ????????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 }
Netty之二进制文件传输
原文地址:http://www.cnblogs.com/xdecode/p/7978147.html