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中的数据传输都是使用的字节类型,下面通过一个实例进行说明,该实例中服务器接受请求 ...
随机推荐
- js实现获取短信验证码倒计时
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- linux学习(九)set_uid、set_gid、stick_bit、软链接、硬链接
一.set_uid set_uid其实是一种特殊权限,我们看一个文件: [root@iZ25lzba47vZ ~]# ls -l /usr/bin/passwd -rwsr-xr-x. root ro ...
- Javascript中的Trait与代码重用
Javascript中的Trait与代码重用 来源 http://www.ituring.com.cn/article/64103 我们知道,OOP中最普遍的代码重用方式是通过继承,但是,继承有一些缺 ...
- 2016 ICPC总结
2016 ICPC总结 九月份开学,开始知识点的补充,刚开始的几周都在刷acmsteps,十月开始进行专题性的学习,首先进行的数据结构,给自己定的计划,十一月前看完数据结构,刚开始的时候看的都是以前的 ...
- robotframework自动化系列:新增流程
刚接手项目的时候,要求所有流程在上线之前必须确保正向操作是正确的:这个时候又有新的模块需要测试,所以引入自动化测试是非常有必要的!通过对比,尝试使用RF进行自动化的回归测试. 测试中最常见的操作就是增 ...
- [深度学习]实现一个博弈型的AI,从五子棋开始(2)
嗯,今天接着来搞五子棋,从五子棋开始给小伙伴们聊AI. 昨天晚上我们已经实现了一个五子棋的逻辑部分,其实讲道理,有个规则在,可以开始搞AI了,但是考虑到不够直观,我们还是顺带先把五子棋的UI也先搞出来 ...
- canvas画布实现手写签名效果
最近项目中涉及到移动端手写签名的功能需求,将实现代码记录于此,供小伙伴们参考指摘哦~ HTML代码: <!--手写区--> <div class="mSign_signMa ...
- .NET读取Excel文件的三种方法的区别
ASP.NET读取Excel文件方法一:采用OleDB读取Excel文件: 把Excel文件当做一个数据源来进行数据的读取操作,实例如下: public DataSet ExcelToDS(strin ...
- .net core 依赖注入扩展,实现随处控制反转
在使用.net core时,依赖注入,主要使用通过构造函数注入.小编将通过扩展方式,实现在类中各个地方可以控制反转,获取实例. 1.首先自定义扩展类 using Microsoft.AspNetCor ...
- [转载] Java集合---HashMap源码剖析
转载自http://www.cnblogs.com/ITtangtang/p/3948406.html 一.HashMap概述 HashMap基于哈希表的 Map 接口的实现.此实现提供所有可选的映射 ...