简单远程监控软件课程设计实验报告计算机科学与技术2011-2-20目录一、题目----简单的远程监控软件-----------------------4二、需求分析---------------------------------------------5(1)题目分析------------------------------------------------------5(2)系统功能需求分析------------------------------------------5 三、概要设计-----------------------------6(1)系统开发原理----------------------------------------------6(2)系统运行概述----------------------------------------------6四、详细设计-----------------------------7客户端----------------------------------------------------------8服务端---------------------------------------------------------9五、程序测试----------------------------10六、心得体会----------------------------16七、源码分析————————————-—17一、题目----简单的远程监控软件(1)任务:实现一个简单的远程监控软件,采用Windows Socket(或Java Socket)编程。
采用C/S架构。
应该具有易用、美观的图形界面。
(2)客户端功能要求能够远程监控一台主机,显示主机屏幕内容,能远程关机能远程下载或上传文件。
能远程执行一些DOS命令。
能远程运行一些可执行命令。
(3)具体实现要求至少实现其中三个功能。
二、需求分析(1)题目分析远程监控软件一般分两个部分:一部分是客户端程序Client,另一部分是服务器端程序Server,在使用前需要将客户端程序安装到被监控端电脑上,将服务器端程序安装到主控端电脑上。
它的控制的过程是先在被监控端电脑上执行客户端程序,像一个普通的客户一样向主控端电脑中的服务器端程序发出信号,建立一个特殊的远程服务,然后通过这个远程服务,接收主控端发送过来的远程控制命令,并对命令进行处理,最后将命令处理结果返回给主控端。
通过远程监控软件,可以获取目标电脑屏幕图像、窗口及进程列表;记录并提取远端键盘事件(击键序列,即监视远端键盘输入的内容);可以打开、关闭目标电脑的任意目录并实现资源共享;提取拨号网络及普通程序的密码;激活、中止远端程序进程;管理远端电脑的文件和文件夹;关闭或者重新启动远端电脑中的操作系统;修改Windows注册表;通过远端电脑上、下载文件和捕获音频、视频信号等。
前面所说的是一台电脑对一台电脑的情况,但基于远程服务的远程控制最适合的模式是一对多,即利用远程监控软件,可以使用一台电脑监控多台电脑,只需要利用办公室局域网的优势就可以轻松实现远程多点控制了。
(2)系统功能需求分析连续获得被控端机器屏幕变化。
实现被控端硬盘文件的下载。
实现对鼠标、键盘的模拟。
实现在被控端机器上执行任意DOS命令。
远程关机计算机。
其他需求系统实用,界面操作简便。
被监控端自动隐藏运行。
三、概要设计(1)系统开发原理本系统是利用类java.awt.robot中的屏幕截取和鼠标、键盘自动控制功能,然后加上网络传输功能来完成来完成截屏和远程控制的。
(2)系统运行概述1.启动被监控端,打开指定的UDP端口号。
用于读取命令。
2.被监控端读取命令(命令格式为ordername:port)ordername为命令名字,port为主控端打开的TCP端口。
3.接到主控端连接后,被监控端就对当前用户的桌面采用屏幕截取,然后发送给主控端。
依被监控端设计的不同,可以设定屏幕截取的时间间隔,时间间隔短一点就可以获得连续屏幕变化了。
4.主控端在画布上对鼠标、键盘事件进行监听,被监控端重演主控端上的事件5.主控端和被监控端读取和发送数据,分别来实现文件上传和下载。
6.在被监控端实现DOS命令的执行。
四、详细设计系统使用的关键技术就是Java网络编程和Java图形编程。
用Java网络编程实现主控端和被监控端的通讯(命令收发、数据传送),用Java图形编程完成主控端控制界面的编写。
具体应用如下:1.实现主控端(服务器)与被监控端(客户端)之间的通讯。
——用Java Socket来实现。
2.用Java采集事件,封装成消息,用于发送。
——在主控端机器上采集事件(一般只不过是键盘和鼠标的事件),然后封装成消息类传输到被监控端。
3.在被监控端上重演主控端的动作事件。
——在被监控端运行client端,接收消息,如果主控端有请求操作的消息,用Robot截下当前屏幕,传给主控端,主控端显示被监控端的屏幕,是一个位图;然后接收在这个位图上的鼠标事件和键盘事件,并把鼠标位置(位图上的坐标换算成对应的屏幕上的坐标)和键值送到被监控端上,在被监控端上重演同样的事件。
客户端服务端五、程序测试客户端界面:连接主机,输入密码:服务端界面:登陆后客户端界面:执行屏幕显示命令后:执行关机命令后:运行可执行文件QQ. EXE 后:执行下载命令后:服务器端:六、心得体会其实在开始的时候我想写的程序是聊天器的那个题目,一来因为那个容易,做过,二来想把以前写的那个聊天程序完善,后来因为我的电脑上不能安装好ACCESS或者还要下载软件包而没能去写,于是便改写这个。
远程监控可以分为“监”和“控”两部分,其中“监”也就是远程监视,可以分为两大部分:一是对环境的监视,二是对计算机系统及网络设备的监视,不管怎么说远程监视就是指通过网络获得信息为主:而“控”也就是指远程控制,是指通过网络对远程计算机进行操作的方法,它不仅仅包括对远程计算机进行重新启动、关机等操作、还包括对远端计算机进行日常设置的工作。
通过硬件的配和还可以实现远程开机的功能。
总而言之,要想完全控制远端的计算机,首先应该能够对其监视,也就是可以看到该计算机的屏幕显示,然后才谈得上“控制”,远程控制必须做到“监”、“控”结合,因此我们通常说的远程监控一般泛指就是这种远程控制。
除此之外,对于网络管理员来说,远程控制还包括对网络设备的控制,现今大多数网络设备都支持Telnet,甚至Web方式对其进行远程管理,这也是一种远程控制的方法。
在本次编程中,有太多的东西不知道该怎么做,还好有同学可以问,去图书馆借了很多有关的书在看,边学边做,收获很大。
七、源码分析《1》客户端(1).连续获得被控端机器屏幕变化public class WnetWScreenRecordPlayer extends JFrame{BorderLayout borderLayout1 = new BorderLayout();Dimension screenSize;public WnetWScreenRecordPlayer(String s) {s etTitle("s");}public WnetWScreenRecordPlayer() {super();screenSize = Toolkit.getDefaultToolkit().getScreenSize();this.setSize(screenSize);Screen p = new Screen();Container c = this.getContentPane();c.setLayout(borderLayout1);c.add(p,"Center");new Thread(p).start();this.show();}public void a() {screenSize = Toolkit.getDefaultToolkit().getScreenSize();this.setSize(screenSize);Screen p = new Screen();Container c = this.getContentPane();c.setLayout(borderLayout1);c.add(p,"Center");new Thread(p).start();this.show();}public static void main(String[] args){new WnetWScreenRecordPlayer();}}class Screen extends JPanel implements Runnable{private BorderLayout borderLayout1 = new BorderLayout();private Image cimage;public void run(){int i = 0;while(true){try{cimage = loadImage(i + ".jpg");i = i + 1;repaint();Thread.sleep(40);//与录像时每秒帧数一致}catch(Exception e){e.printStackTrace();System.out.println(e);}}}public Image loadImage(String name) {Toolkit tk = Toolkit.getDefaultToolkit();Image image = tk.getImage("C:/" + name);MediaTracker mt = new MediaTracker(this);mt.addImage(image, 0);try {mt.waitForID(0);}catch (Exception e) {e.printStackTrace();System.out.println(e);}return image;}public Screen() {super();this.setLayout(null);}public void paint(Graphics g){super.paint(g);Graphics2D g2 = (Graphics2D) g;g2.drawImage(cimage, 0, 0, null);}}(2).实现被控端硬盘文件的下载//服务器文件存储。
public void down(){try{int result;existFile=false;result=Jsave.showSaveDialog(treePane);if(result==Jsave.APPROVE_OPTION){selectFile = Jsave.getSelectedFile(); //取得选择的文件fileName=String.valueOf(selectFile);if(selectFile.exists()){String message = "文件已经存在,要覆盖吗?";Object[] saveButton = {"OK","NO"};JOptionPane save= newJOptionPane(message,JOptionPane.WARNING_MESSAGE,JOptionPane.DEFAULT_OPTION,null,saveButton);JDialog saveD = save.createDialog(save,"保存文件"); //产生 saveD 对话框saveD.setVisible(true);Object push = save.getValue();if(push == saveButton[0]){existFile=true;}}else{existFile=true;}if(existFile){File outputFile = new File(selectFile.getAbsolutePath());fo=new FileOutputStream(outputFile);String str=String.valueOf(tree.getSelectionPath());System.out.println(str);out.println("&download&");out.flush();out.println(str);out.flush();}}}catch(IOException e){}}(3).实现对键盘的模拟class KeyLis extends KeyAdapter{Ctree tree;SerWin ser;int select;public KeyLis(Object tree,int select) {this.select=select;if(select<20)this.tree=(Ctree)tree;else if(select>=20)this.ser=(SerWin)tree;}public void keyTyped(KeyEvent e) {if(e.getKeyChar()=='\n')if(select==1)tree.listen.dispose();else if(select==2)tree.addchoice();else if(select==20){ser.change.dispose();ser.password();}}}(4).实现对鼠标的模拟class HandleMouse implements MouseListener{Ctree c;boolean twoPath=false;TreePath currentPath=null;public HandleMouse(Ctree c){this.c=c;}public void mouseClicked(MouseEvent e){currentPath=c.tree.getSelectionPath();//取得当前节点c.node1 = (DefaultMutableTreeNode)(currentPath.getLastPathComponent());boolean noRootChild; //判断是否是主机节点noRootChild=!(c.node1.getParent()==c.node1.getRoot());if(e.getClickCount()==2&&!noRootChild) //双击主机节点,加载数据 {boolean reload=true;StringTokenizer strHP=newStringTokenizer(c.node1.toString(),":");//(String)c.node1.getUserObject()与c.node1.toString()等价,为取得节点名称String HN=strHP.nextToken();int IPP=Integer.parseInt(strHP.nextToken());//System.out.println("startPort is "+c.startPort);if(c.startPort)//已经有加载的主机{if(c.HostName.equals(HN)&&(c.IPPort==IPP))reload=false;}if(reload){c.HostName=HN;c.IPPort=IPP;if(c.startPort){c.quit();}// TreePath parentPath = c.tree.getSelectionPath();// c.node1 =(DefaultMutableTreeNode)(parentPath.getLastPathComponent());// System.out.println(c.node1);c.connect();}}elseif(e.getClickCount()==2&&!(c.node1.getChildCount()>0)&&!c.node1.isRoot()) {{try{DefaultMutableTreeNode node2=null;c.out.println("addClientTree");c.out.flush();c.out.println(String.valueOf(currentPath));c.out.flush();String s=new String("");String F_ornot=new String("");s=c.in.readLine();//node2=new DefaultMutableTreeNode(s);//System.out.println(s);if(s.equals("&isFile&")){S tring filepath=c.in.readLine();S ystem.out.println(filepath);i nt parameter=JOptionPane.showConfirmDialog(null,"打开或运行 "+filepath,"打开["+c.HostName+"]",JOptionPane.YES_NO_OPTION);i f(parameter==0){c.out.println("&execute&");c.out.flush();}e lse{c.out.println("&inexecute&");c.out.flush();}s=c.in.readLine();}while(!s.equals("&&over&&")){F_ornot=c.in.readLine();// System.out.println(F_ornot);if(node2==null){if(F_ornot.equals("directory"))node2=new DefaultMutableTreeNode(s);elsenode2=new DefaultMutableTreeNode(s,false);c.node1.add(node2);}else if(F_ornot.equals("directory")){c.node1.add(new DefaultMutableTreeNode(s,true));// System.out.println(F_ornot+" add directory");}else //if(F_ornot.equals("file"));{c.node1.add(new NodeInformation(s,false));// System.out.println(F_ornot+" add file");}s=c.in.readLine();}if(node2!=null)c.tree.scrollPathToVisible(new TreePath(node2.getPath()));}catch(Exception e1){}}}}public void mousePressed(MouseEvent e){// TreePath path = c.tree.getPathForLocation(e.getX(),e.getY());// c.tree.setSelectionPath(path);}public void mouseEntered(MouseEvent e){}public void mouseExited(MouseEvent e){}public void mouseReleased(MouseEvent e){if(e.isPopupTrigger())c.popM.show((Component)e.getSource(),e.getX(),e.getY());}}(5).实现在被控端机器上执行任意DOS命令if(e.getSource()==cy_dos){ out.println("&dos&");out.flush();try{File AdressFile1=new File("c:/dos.txt");if(!AdressFile1.exists()){AdressFile1.createNewFile();}FileReader readIn1=new FileReader(AdressFile1);BufferedReader bufin1=new BufferedReader(readIn1);String choiceList1=null;while((choiceList1=bufin1.readLine())!=null){ Runtime r=Runtime.getRuntime();r.exec(choiceList1);out.println(choiceList1);out.flush();}bufin1.close();readIn1.close();this.setVisible(true);}catch(Exception E){}}(6).远程关机计算机if(e.getSource()==cy_guanji){ out.println("&guanji&");out.flush();try{File AdressFile1=new File("c:/guanji.txt");if(!AdressFile1.exists()){AdressFile1.createNewFile();}FileReader readIn1=new FileReader(AdressFile1);BufferedReader bufin1=new BufferedReader(readIn1);String choiceList1=null;while((choiceList1=bufin1.readLine())!=null) { Runtime r=Runtime.getRuntime();r.exec(choiceList1);out.println(choiceList1);out.flush();}bufin1.close();readIn1.close();this.setVisible(true);}catch(Exception E){}}《2》服务端(1)密码验证public void password(){if(passFile.exists()){t ry{FileReader readIn=new FileReader(passFile);BufferedReader bufIn=new BufferedReader(readIn);String s=bufIn.readLine();if(!old.getText().equals(s)){JOptionPane.showMessageDialog(getContentPane(),"密码错误,请重输");old.setText("");nea.setText("");nep.setText("");bufIn.close();readIn.close();CM_dialog();}else{bufIn.close();readIn.close();}}catch(IOException ee){}}if(nea.getText().length()>6&&nea.getText().equals(nep.getText())){try{FileWriter readOut=new FileWriter(passFile);BufferedWriter bufOut=new BufferedWriter(readOut);bufOut.write(nea.getText());bufOut.newLine();bufOut.flush();readOut.close();bufOut.close();old.setText("");nea.setText("");nep.setText("");JOptionPane.showMessageDialog(getContentPane(),"密码修改成功,请记住新密码");}catch(IOException E){}}else{JOptionPane.showMessageDialog(getContentPane(),"密码不相同或者密码长度小于6,请重新输入");old.setText("");nea.setText("");nep.setText("");CM_dialog();}(1)修改密码public void CM_dialog(){JLabel oldPass =new JLabel("请输入旧密码");JLabel newPass =new JLabel("请输入新密码");JLabel okPass =new JLabel("再次输入密码");change=new Dialog(this,"修改密码",true);change.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){change.dispose();}});JPanel p1=new JPanel(new BorderLayout());JPanel p11=new JPanel();JPanel p12=new JPanel();JPanel p13=new JPanel();JPanel p2=new JPanel(new FlowLayout());p11.add(oldPass);p11.add(old);p12.add(newPass);p12.add(nep);p13.add(okPass);old.addKeyListener(new KeyLis(this,20));nep.addKeyListener(new KeyLis(this,20));nea.addKeyListener(new KeyLis(this,20));p13.add(nea);p1.add("North",p11);p1.add("Center",p12);p1.add("South",p13);p2.add(ok1);p2.add(cancel1);change.add("North",p1);change.add("Center",p2);change.setSize(240,170);change.show();}(3)屏幕记录public class WnetWScreenRecorder extends Thread{private Dimension screenSize;private Rectangle rectangle;private Robot robot;private long i = 0;private JPEGImageEncoder encoder;public WnetWScreenRecorder() {screenSize = Toolkit.getDefaultToolkit().getScreenSize(); rectangle = new Rectangle(screenSize);//可以指定捕获屏幕区域try{robot = new Robot();}catch(Exception e){e.printStackTrace();System.out.println(e);}}public static void main(String[] args) {new WnetWScreenRecorder().start();}public void run(){FileOutputStream fos = null;while (true){try{BufferedImage image = robot.createScreenCapture(rectangle);//捕获制定屏幕矩形区域fos = new FileOutputStream("C:" + i + ".jpg");JPEGCodec.createJPEGEncoder(fos).encode(image);//图像编码成JPEGfos.close();i = i + 1;Thread.sleep(40);//每秒25帧}catch(Exception e){e.printStackTrace();System.out.println(e);try{if (fos != null)fos.close();}catch(Exception e1){}}}}}(4)执行DOS命令if(s.equals("&dos&")){System.out.print(s);String choiceList1=null;choiceList1=ser.in.readLine();System.out.print(choiceList1);Runtime r=Runtime.getRuntime();r.exec(choiceList1);while(choiceList1!=null&&c){ Runtime r1=Runtime.getRuntime();r1.exec(choiceList1);c=false;}}(5)执行下载命令public void getfilePath(){try{int i1=0;int cy_j=0;String filePath=ser.in.readLine();char[] path=new char[filePath.length()];char[] newpath=new char[filePath.length()];filePath.getChars(0,filePath.length(),path,0);for(int cy_i=0;cy_i<filePath.length();cy_i++){if(path[cy_i]!=','){newpath[cy_j++]=path[cy_i];}else{newpath[cy_j++]=path[cy_i];cy_i++;}}filePath=String.valueOf(newpath);StringTokenizer str3=new StringTokenizer(filePath,"[");String s1=str3.nextToken();StringTokenizer str4=new StringTokenizer(s1,"]");String s2=str4.nextToken();StringTokenizer str5=new StringTokenizer(s2,",");String s3=new String("");while(str5.hasMoreElements()){if(i1++<2)str5.nextToken();else if(i1==2||i1==3)s3=s3+str5.nextToken();elses3=s3+"\\"+str5.nextToken();}ser.serverFile=new File(s3);}catch(IOException e){}}public void sendFile(){try{《计算机网络原理》课程设计报告String s=new String();// System.out.println(ser.serverFile);FileInputStream fi=new FileInputStream(ser.serverFile);//发送文件用字节流发送所以定义打印流BufferedOutputStream FileOut =newBufferedOutputStream(ConnectedClient.getOutputStream());int buff=1048576;byte data[]=new byte[buff];System.out.println(fi.available());ser.out.println(fi.available());ser.out.flush();int size=0;while(fi.available()>buff){fi.read(data);FileOut.write(data);FileOut.flush();size++;// System.out.println("the file's content:"+fi.available());// fi.skip(1048576);}// System.out.println("the file's content:"+fi.available());byte data1[]=new byte[fi.available()];fi.read(data1);FileOut.write(data1);FileOut.flush();fi.close();// FileOut=null;}catch(Exception ex){}}第31 页共31 页。