Netty+Telnet定时上传文件和多线程执行不同操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36688143/article/details/85006626

需求

1)使用netty搭建一个服务端程序和一个客户端程序

2)客户端把上一个Demo的错误日志(就是你想要上传的文件)上传到服务端程序,如果想了解我上一个Demo点击这里

3)拓展功能,实现定时上传错误日志及可以使用telnet连接服务器手动控制上传错误日志

4)使用多线程拓展netty服务端,netty只负责收发消息,逻辑提交到其它线程处理

5)使用java反射技术改造程序,比如telnet用upload就调用upload方法上传数据,
调用display就调用display方法显示服务端上一次接收到的数据 
 

先看Netty服务端和客户端的基本执行过程

1)初始化
2)初始化的时候new一个handler
3)在handler中执行方法
4)互相连接时触发channelActive,channelRead负责监听消息

代码效果

服务端

客户端

telnet中

打开控制台,输入telnet localhost 8888或者下图所示

  连接后即可在窗口中输入不同指令来执行操作(暂时只对upload指令) 

源代码链接导入IDE即可直接使用点击这里

代码思路:服务端

1、启动FileUploadServer

    1)创建一个线程开启telnet服务端,用于接收telnet发送的指令
         Thread telnetTread = new Thread(new TelnetServer());  

2、调用TelnetServer

    1)TelnetServer的run()方法保存接收到的telnetClient指令

if(tmp != null && "upload".equalsIgnoreCase(tmp.trim())){
   FileUploadServer.command = tmp;
   out.println("ok!uploading...");
} else if(tmp != null && "display".equalsIgnoreCase(tmp.trim())) {
   FileUploadServer.command = tmp;
   if(FileUploadServer.uploadData.getNewFileName() == null) {
      out.println("no file uploaded!");
   } else {               
      out.println("last uploaded file: " + FileUploadServer.uploadData.getNewFileName());
   }
} else {
   out.println("invalidate instruction!");
}

 

    2)FileUploadServerHandler类的channelRead(ChannelHandlerContext ctx, Object msg)方法监听指令,根据指令值执行不同操作(此处只对"upload"指令进行操作)

if("upload".equals(methodName.toLowerCase())){
   comfirmUpload = true;
   //FileUploadServer.command = null;
}

    3)FileUploadServerHandler调用BusinessThreadUtil类使用java的反射机制执行当指令为"upload"时候的操作

if(comfirmUpload) {
//handler中,使用异步的线程池处理业务。防止handler卡住,导致netty并发性能不佳
   Class<?> clazz = Class.forName("com.hx.util.BusinessThreadUtil");
   Method method = clazz.getMethod("upload",Object.class, String.class);
   method.invoke(null,msg, fileDir);
}

    4)BusinessThreadUtil类调用UploadServerThread的run()方法保存上传的文件到服务端本地

//private RandomAccessFile raf;

raf = new RandomAccessFile(file, "rw");
raf.seek(0);

//保存
raf.write(bytes, 0, bytes.length);

 

代码思路:客户端

1、启动FileUploadClient

2、与服务端连接成功,触发FileUploadServerHandler的channelActive(ChannelHandlerContext ctx)方法

此时执行FileUploadClientHandler类的channelActive(ChannelHandlerContext ctx)方法,调用UploadClientTimerTask类的timerTask()方法开始定时上传文件的任务

UploadClientTimerTask uctt = new UploadClientTimerTask();
uctt.timerTask(path,errorLogPath,ctx);

     1)UploadClientTimerTask类的timerTask()方法调用LogFilterUtil类,过滤日志文件,得到的异常信息是一段String

LogFilterUtil.logFilter(path,errorLogPath);

    2)UploadClientTimerTask类的timerTask()方法调用bean实体类UploadData,保存过滤的内容,并向客户端发送要上传的对象

//private RandomAccessFile raf;

// r:只读

randomAccessFile = new RandomAccessFile(file, "r");
randomAccessFile.seek(0);//从开始位置开始读
long length = randomAccessFile.length();

//创建一个大小为文件长度的字节数组
byte[] bytes = new byte[(int) length];

//将文件读入字节数组,一次读完
randomAccessFile.read(bytes);
uploadData.setData(bytes);
uploadData.setOrignFileName(file.getName());

//向客户端发送要上传的对象              
ctx.writeAndFlush(uploadData);  

    3)UploadClientTimerTask类的timerTask()方法调用addTask(this);方法自身递归,根据每个solt执行定时任务

//根据时长把task任务放到响应的solt上
timer.newTimeout(task, 100, TimeUnit.MILLISECONDS);

ps:我只是搬运工,代码所有权一位兄dei

猜你喜欢

转载自blog.csdn.net/qq_36688143/article/details/85006626