Netty之二进制文件传输
传输会话简要
客户端发起一个文本请求给服务器端, 服务器端解析里面文本, 返回文件给客户端, 客户端解析文件

服务器端
因为示例文件比较小, 所以没有做分段传输, 而是直接一次性把整个文件byte[]都发给客户端了.
如果需要传输大文件, 则需要做粘包拆包, 参考另外一篇博文 Netty之粘包分包
需要三个ChannelPipeline
// 解析客户端发送的文本json
pipeline.addLast(new StringDecoder());
// 二进制文件加密传输
pipeline.addLast(new ObjectEncoder());
// 业务逻辑
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
// 传输文本给服务器端
p.addLast(new StringEncoder());
// 二进制文件获取解析
p.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(this
.getClass().getClassLoader())));
// 客户端业务代码
p.addLast(new FileClientHandler());
FileClientHandler业务逻辑
@Override
public void channelActive(ChannelHandlerContext ctx) {
try {
// 将要获取的pdf路径发送给服务器端
JSONObject jo = JSONObject.create().put("path", "d:\\a.pdf");
ctx.writeAndFlush(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
PDFContent content = (PDFContent) msg;
// 从服务器端获取的二进制文件存到本地
String fileName = UUID.randomUUID().toString() + ".pdf";
File file = new File("D:\\" + fileName);
try {
FileOutputStream out = new FileOutputStream(file);
IOUtils.copyBinaryTo(new ByteArrayInputStream(content.getContent()), out);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
JSONObject jo = JSONObject.create().put("res", "Thank You, I Have The File!");
ctx.writeAndFlush(jo.toString());
ctx.close();
} catch (JSONException e) {
e.printStackTrace();
}
}
完整的代码如下
FileClient & FileClientHandler
package test; import com.fr.general.IOUtils;
import com.fr.json.JSONException;
import com.fr.json.JSONObject;
import com.fr.stable.core.UUID;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
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 io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.string.StringEncoder; import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; public class FileClient { public FileClient(){ } public void start() {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() { @Override
protected void initChannel(SocketChannel s) throws Exception {
ChannelPipeline p = s.pipeline();
// 传输文本给服务器端
p.addLast(new StringEncoder());
// 二进制文件获取解析
p.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(this
.getClass().getClassLoader())));
// 客户端业务代码
p.addLast(new FileClientHandler());
}
});
ChannelFuture future = bootstrap.connect("localhost", 7766).sync();
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
} public static void main(String[] args) throws InterruptedException {
new FileClient().start();
} private static class FileClientHandler extends ChannelInboundHandlerAdapter { @Override
public void channelActive(ChannelHandlerContext ctx) {
try {
// 将要获取的pdf路径发送给服务器端
JSONObject jo = JSONObject.create().put("path", "d:\\a.pdf");
ctx.writeAndFlush(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
PDFContent content = (PDFContent) msg;
// 从服务器端获取的二进制文件存到本地
String fileName = UUID.randomUUID().toString() + ".pdf";
File file = new File("D:\\" + fileName);
try {
FileOutputStream out = new FileOutputStream(file);
IOUtils.copyBinaryTo(new ByteArrayInputStream(content.getContent()), out);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
JSONObject jo = JSONObject.create().put("res", "Thank You, I Have The File!");
ctx.writeAndFlush(jo.toString());
ctx.close();
} catch (JSONException e) {
e.printStackTrace();
}
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
}
FileServer & FileServerHandler
package test; import com.fr.json.JSONObject;
import com.fr.stable.StringUtils;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
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.codec.serialization.ObjectEncoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler; import java.io.FileInputStream; public class FileServer { private FileServer() {
startServer();
} private void startServer() {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try{
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 解析客户端发送的文本json
pipeline.addLast(new StringDecoder());
// 二进制文件加密传输
pipeline.addLast(new ObjectEncoder());
// 业务逻辑
pipeline.addLast(new FileServerHandler());
}
});
ChannelFuture future = bootstrap.bind("localhost", 7766).sync();
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
} } private class FileServerHandler extends ChannelInboundHandlerAdapter { @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 获取到客户端请求, 解析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"));
}
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
} public static void main(String[] args){
// 启动Server
new FileServer();
} }
PDFContent
package test; import java.io.Serializable; /**
* 文件的封装
*/
public class PDFContent implements Serializable{ private byte[] content; public byte[] getContent() {
return content;
} public void setContent(byte[] content) {
this.content = content;
}
}
Netty之二进制文件传输的更多相关文章
- [netty4][netty-transport]netty之nio传输层
[netty4][netty-transport]netty之nio传输层 nio基本处理逻辑 查看这里 Selector的处理 Selector实例构建 NioEventLoop.openSelec ...
- WebService之Axis2(4):二进制文件传输
在<WebService大讲堂之Axis2(2):复合类型数据的传递>中讲过,如果要传递二进制文件(如图像.音频文件等),可以使用byte[]作为数据类型进行传递,然后客户端使用RPC方式 ...
- netty中的传输
终于在课设的闲时间把netty实战的四五章给解决了 这里来记录一下第四章里面所讲的IO 首先说到IO,我想,必须要先了解阻塞,非阻塞,同步和异步这四个词 看到一个讲的很易懂的例子:https://ww ...
- Netty 框架学习 —— 传输
概述 流经网络的数据总是具有相同的类型:字节,这些字节如何传输主要取决于我们所说的网络传输.用户并不关心传输的细节,只在乎字节是否被可靠地发送和接收 如果使用 Java 网络编程,你会发现,某些时候当 ...
- netty的对象传输
pom <!-- https://mvnrepository.com/artifact/io.netty/netty-all --> <dependency> <grou ...
- netty 对象序列化传输示例
package object.server.impl; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Chann ...
- Netty进行文件传输
本次是利用TCP在客户端发送文件流,服务端就接收流,写入相应的文件. 实验的源文件是一个图片,假设地址是D:\\Koala.jpg,接收保存后的图片为D:\\test.jpg 原理就是将文件读取成by ...
- 快来体验快速通道,netty中epoll传输协议详解
目录 简介 epoll的详细使用 EpollEventLoopGroup EpollEventLoop EpollServerSocketChannel EpollSocketChannel 总结 简 ...
- 【Netty】Netty传输
一.前言 在简单学习了Netty中的组件后,接着学习Netty中数据的传输细节. 二.传输 2.1 传输示例 Netty中的数据传输都是使用的字节类型,下面通过一个实例进行说明,该实例中服务器接受请求 ...
随机推荐
- Quartz.NET的使用(附源码)
简介 虽然Quartz.NET被园子里的大神们写烂了,自己还是整理了一篇,结尾会附上源码地址. Quartz.NET是一款功能齐全的开源作业调度框架,小至的应用程序,大到企业系统都可以适用.Quart ...
- 2016 ACM/ICPC Asia Regional Dalian Online Football Games
Football Games Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
- Centos6.8 安装tomcat8.5.11
1.下载 安装包 wget http://mirrors.aliyun.com/apache/tomcat/tomcat-8/v8.5.11/bin/apache-tomcat-8.5.11.tar. ...
- AngularJS学习篇(十八)
AngularJS API AngularJS 全局 API 用于执行常见任务的 JavaScript 函数集合,如: 比较对象 迭代对象 转换对象 全局 API 函数使用 angular 对象进行访 ...
- 使用(Unicode字符)让inline水平元素换行
为了实现上面效果: <dl> <dt>提问:</dt><dd>为什么没有男朋友?</dd> </dl> <dl ...
- 学习C++ -> 构造函数与析构函数
学习C++ -> 构造函数与析构函数 一.构造函数的介绍 1. 构造函数的作用 构造函数主要用来在创建对象时完成对对象属性的一些初始化等操作, 当创建对象时, 对象会自动调用 ...
- javascript 中parseInt 的用法
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8 ...
- Breadth-first search 算法(Swift版)
在讲解Breadth-first search 算法之前,我们先简单介绍两种数据类型Graph和Queue. Graph 这就是一个图,它由两部分组成: 节点, 使用圆圈表示的部分 边, 使用线表示的 ...
- C++使用htslib库读入和写出bam文件
有时候我们需要使用C++处理bam文件,比如取出read1或者read2等符合特定条件的序列,根据cigar值对序列指定位置的碱基进行统计或者对序列进行处理并输出等,这时我们可以使用htslib库 ...
- 8. 理解ZooKeeper的内部工作原理
到目前为止,我们已经讨论了ZooKeeper服务的基础知识,并详细了解了数据模型及其属性. 我们也熟悉了ZooKeeper 监视(watch)的概念,监视就是在ZooKeeper命名空间中的znode ...