前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >远程过程调用 Java RMI 技术 远程控制

远程过程调用 Java RMI 技术 远程控制

原创
作者头像
世玉
修改2020-09-09 18:09:00
9540
修改2020-09-09 18:09:00
举报
文章被收录于专栏:世玉的专栏世玉的专栏

前段时间空闲时期,研究了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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档