前段时间空闲时期,研究了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();
}
}
}
}
}
其余的文件没有什么作用。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。