远程过程调用 Java RMI 技术 远程控制
时间:2022-07-24
本文章向大家介绍远程过程调用 Java RMI 技术 远程控制,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
前段时间空闲时期,研究了commonlang3 的jar包。无意中搜索到了RMI 远程过程调用的相关知识。并实际测试了一番。现特此记录以下以备将来不时之需。
远程过程调用是一项 用于在本地执行代码,让远程的计算机执行相应的代码的一项技术。 举个例子。 本地写了一个 hello world . 通过RMI 协议。本地执行以后,远程也会执行hello world 。同理,本地开个计算器,远程也可以开个计算器。 本地执行一段 CMD指令。远程也会执行相应指令。想想是不是很可怕?如果被人恶意利用,甚至能达到控制整个服务器的权限。当然合理使用,还是有很大帮助的。比如实现分布式计算。 真正的同时控制多个服务器执行事件。 也可以做到搭建一个中心服务器。 发送指令以后,多个从服务器向主服务器下载代码,实现批量更新升级等。 游戏服务器经常分区。什么1区 。2 区等等。 如果挨个手动的更新,是一个很痛苦的事情。但是如果利用RMI 技术,即可实现批量更新。
如图搭建普通的Java项目
RMI 协议需要一个客户端 , 本地执行代码。 一个服务端 放置在被控机上面运行。
client.java 的代码如下:
import java.io.File;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Date;
public class Client {
public static void main(String[] args) {
try {
ServerI iTimeServer = (ServerI) Naming.lookup("rmi://localhost:8980/t1");
System.out.println("服务器时间:"+new Date(iTimeServer.getServerTime() ) );
String path="C:\TEMP\";
System.out.println("文件路径:"+path + "result.txt");
String command="cmd /k ipconfig>>"; //追加内容到文件
System.out.println("执行命令:"+iTimeServer.action(command +path+ "result.txt"));
Thread.sleep(5*1000l);
System.out.println( iTimeServer.readToString(path+"result.txt"));
iTimeServer.downloadNetFile("http://car.mozile.cn/upload/app/11.png", path, "11.png");
} catch (NotBoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
由于RMI 很难实现回显结果。所以我采用了一个方案绕过问题,就是把结果写入到一个记事本里面。然后通过下载读取文件流的方式,查看执行结果。由于时间上不能很好掌控。所以我加了延时读取文本,确保结果可以被顺利读取到。
服务器的代码如下:
import java.io.IOException;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.RMISocketFactory;
public class Run {
public static void main(String[] args) {
try {
RMISocketFactory.setSocketFactory(new SMRMISocket());
ServerI server = new ServerImp();
LocateRegistry.createRegistry(8980);
Naming.rebind("//localhost:8980/t1",server);
System.out.println("Bind is Finish");
} catch (RemoteException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器端代码是放置在被控机上,并运行的。
RMI接口:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface ServerI extends Remote{
public String action(String arg)throws RemoteException;
int add(int a,int b) throws RemoteException;
long getServerTime() throws RemoteException;
String readToString(String path) throws RemoteException;
void downloadNetFile(String netpath,String localpath,String newName) throws RemoteException;
}
RMI实现类:
import java.rmi.RemoteException;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
public class ServerImp extends UnicastRemoteObject implements ServerI {
public ServerImp() throws RemoteException {
super();
}
public ServerImp(int port) throws RemoteException {
super(port);
// TODO Auto-generated constructor stub
}
public ServerImp(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException {
super(port, csf, ssf);
// TODO Auto-generated constructor stub
}
@Override
public String action(String arg) throws RemoteException {
System.out.println(arg);
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class},
new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke", new Class[]{Object.class,Object[].class},
new Object[]{null, new Object[0]}),
new InvokerTransformer("exec", new Class[]{String.class},
new Object[]{arg})
};
Transformer chain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
innerMap.put("name", "hello");
Map outerMap = TransformedMap.decorate(innerMap, null, chain);
Map.Entry elEntry = (java.util.Map.Entry)outerMap.entrySet().iterator().next();
elEntry.setValue("hello");
return arg;
}
@Override
public int add(int a, int b) throws RemoteException {
// TODO Auto-generated method stub
return a+b;
}
@Override
public long getServerTime() throws RemoteException {
// TODO Auto-generated method stub
return System.currentTimeMillis();
}
@Override
public String readToString(String filePath){
return FileUtil.readToString(filePath);
}
@Override
public void downloadNetFile(String netpath, String localpath, String newName) throws RemoteException {
FileUtil.downloadNetFile(netpath, localpath+newName);
}
}
FileUtil 工具类,用于下载文件等
import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
public class FileUtil {
public static String readToString(String fileName) {
String encoding = "GBK";
File file = new File(fileName);
Long filelength = file.length();
byte[] filecontent = new byte[filelength.intValue()];
try {
FileInputStream in = new FileInputStream(file);
in.read(filecontent);
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
return new String(filecontent, encoding);
} catch (UnsupportedEncodingException e) {
System.err.println("The OS does not support " + encoding);
e.printStackTrace();
return null;
}
}
/**
* 指定位置开始写入文件
* @param tempFile 输入文件
* @param outPath 输出文件的路径(路径+文件名)
* @throws IOException
*/
public static void randomAccessFile( String outPath,File tempFile) throws IOException{
RandomAccessFile raFile = null;
BufferedInputStream inputStream=null;
try{
File dirFile = new File(outPath);
//以读写的方式打开目标文件
raFile = new RandomAccessFile(dirFile, "rw");
raFile.seek(raFile.length());
inputStream = new BufferedInputStream(new FileInputStream(tempFile));
byte[] buf = new byte[1024];
int length = 0;
while ((length = inputStream.read(buf)) != -1) {
raFile.write(buf, 0, length);
}
}catch(Exception e){
throw new IOException(e.getMessage());
}finally{
try {
if (inputStream != null) {
inputStream.close();
}
if (raFile != null) {
raFile.close();
}
}catch(Exception e){
throw new IOException(e.getMessage());
}
}
}
/**
* 删除单个文件
*
* @param fileName
* 要删除的文件的文件名
* @return 单个文件删除成功返回true,否则返回false
*/
public static boolean deleteFile(String fileName) {
File file = new File(fileName);
// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
if (file.exists() && file.isFile()) {
if (file.delete()) {
System.out.println("删除单个文件" + fileName + "成功!");
return true;
} else {
System.out.println("删除单个文件" + fileName + "失败!");
return false;
}
} else {
System.out.println("删除单个文件失败:" + fileName + "不存在!");
return false;
}
}
/***
* 写入到文件
* @param content
* @param FilePath
* @throws IOException
*/
public static void writeFile(String content,String FilePath) throws IOException{
File file = new File(FilePath);
if(!file.exists()){
file.createNewFile();
}
FileWriter fileWriter = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fileWriter);
bw.write(content);
bw.close();
}
/****
* 下载网络文件
* @param neturl
* @param outfilepath
*/
public static void downloadNetFile(String neturl, String outfilepath){
// 下载网络文件
int bytesum = 0;
int byteread = 0;
FileOutputStream fs =null;
try {
URL url = new URL(neturl);
URLConnection conn = url.openConnection();
InputStream inStream = conn.getInputStream();
fs = new FileOutputStream(outfilepath);
byte[] buffer = new byte[1204];
while ((byteread = inStream.read(buffer)) != -1) {
bytesum += byteread;
System.out.println(bytesum);
fs.write(buffer, 0, byteread);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fs!=null){
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
其余的文件没有什么作用。
- CDN加速下通过nginx获取网站访客真实ip
- linux centos7服务器使用密钥登录ssh同时禁止root密码登录
- linux nginx服务器安装verynginx防止CC攻击
- linux nginx安装HttpGuard防止CC攻击
- wordpress您的主机禁用了mail()函数 SMTP邮件通知解决方法
- 我的编程之路:知识管理与知识体系
- UTF-8 为什么会比 UTF-16 浪费?
- 码农也要学算法
- 19 个常用的 JavaScript 简写方法
- 从零开始写 PHP 扩展
- Linux 基础:文件查找 find
- 区块链入门教程
- AI 玩微信小游戏跳一跳的正确姿势,Auto-Jump 算法详解
- 正则表达式实例
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 万字长文,Thread 类源码解析!
- lintCode 31 题解
- JDK1.8HashMap源码学习-put操作以及扩容(二)
- Python 中的数字到底是什么?
- 详解 Python 的二元算术运算,为什么说减法只是语法糖?
- 详解增强算术赋值:“-=”操作是怎么实现的?
- Hyperledger Explorer 环境搭建详解
- [译]在Solidity中创建无限制列表
- java安全编码指南之:声明和初始化
- java安全编码指南之:表达式规则
- java安全编码指南之:Number操作
- 如何提高代码质量
- 小姐姐非要问我:spring编程式事务是啥?
- 阿里3面:Spring声明式事务连环炮,让我措手不及。。
- 旷视科技|商用端侧Raw图像降噪方案