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中的数据传输都是使用的字节类型,下面通过一个实例进行说明,该实例中服务器接受请求 ...
随机推荐
- java自动化-juint框架简述
本人使用的是java的juint框架来组织的自动化测试,故我这边需要简单介绍一下juint框架 首先,建议自行百度一下juint框架,先有一个大概的了解 所谓的接口自动化测试,会对多个接口中每一个接口 ...
- Python Web框架篇:Django Form组件
Form简介 在HTTP中,表单(form标签),是用来提交数据的,其action属性说明了其传输数据的方法:如何传.如何接收. 访问网站时,表单可以实现客户端与服务器之间的通信.例如查询,就用到了表 ...
- 链表倒数第n个节点
找到单链表倒数第n个节点,保证链表中节点的最少数量为n. 样例 给出链表 3->2->1->5->null和n = 2,返回倒数第二个节点的值1. /** * Definiti ...
- 理解Java包
本质上,包是一个唯一命名的类的集合,将类集合到包里面的主要原因,是为了当在应用程序中使用预先编写的类时避免与类自身可能引起的明明冲突.用于包中的类名不会妨碍另一个包或程序中的类名,因为此时,包中的类名 ...
- IdentityServer4 实现自定义 GrantType 授权模式
OAuth 2.0 默认四种授权模式(GrantType): 授权码模式(authorization_code) 简化模式(implicit) 密码模式(password) 客户端模式(client_ ...
- 小明滚出---响应对象HttpServletResponse和请求对象HttpServletRequest实例
<Servlet类的Java> @WebServlet("/studentServlet") public class StudentServlet extends H ...
- 桌面消息通知:HTML5 Notification
先上一段完整代码 //注册权限 Notification.requestPermission(function (status) { // 这将使我们能在 Chrome/Safari 中使用 Noti ...
- 蓝桥杯-算法训练--ALGO-5 最短路
问题描述 给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环).请你计算从1号点到其他点的最短路(顶点从1到n编号). 输入格式 第一行两个整数n, m. 接下来的m行,每行有三个 ...
- win10提示管理员已阻止你运行此应用,如何强制运行
方法/步骤 这里以自己遇到的一个软件为例,下图就是禁止的图画: 在开始菜单中输入"cmd",然后以管理员身份运行: 按住"shift"键,同 ...
- display:none和visibility:hidden区别
<!-- display:none和visible:hidden都能把网页上某个元素隐藏起来,但两者有区别: --> <!-- display:none 不为被隐藏的对象保留其物理空 ...