本案例分两个类Server类和Client类,其余的类为内部类。该案例纯属Java编程。
并且已经在Linux上测试通过。

屏幕监视设计思想:[url]http://www.blackswansoft.com/songhaikang/article/20110221105156640.html[/url]


-------------------------Server类---------------------------------------

import java.awt.AWTException; 


import java.awt.Dimension; 

import java.awt.Rectangle; 

import java.awt.Robot; 

import java.awt.Toolkit; 

import java.awt.image.BufferedImage; 

import java.io.DataOutputStream; 

import java.io.IOException; 

import java.io.InputStream; 

import java.net.ServerSocket; 

import java.net.Socket; 

import java.util.zip.ZipEntry; 

import java.util.zip.ZipOutputStream; 


import javax.imageio.ImageIO;


/**
*使用Java截屏工具,不停的截取当前屏幕图片,图片不需保存直接以流的形式发送的监控端电脑上,并显示出来
*控制端的鼠标和键盘的操作再发送的被控端并且执行从而实现屏幕监控
*可以达到用一台电脑完全控制另外一台电脑
*/

public class Server{ 

 public static void main(String args[]) { 

 SendScreenImg sender=new SendScreenImg(); 

 sender.changeServerPort(30009);//此处可以修改服务端口 

 new Thread(sender).start();//打开图像传输服务 

 OperateWindow operate=new OperateWindow(); 

// operate.changeServerPort(30010);//此处可以修改服务端口 

 new Thread(operate).start();//打开主机操控服务 


 //***** 当然 服务器端的端口修改是随时都可以操作的 它实际上是关闭以前的端口 再开启一个新端口 *****// 

 } 

} 


/**


* @author LanXJ @doctime 2010-7-8
* 开启一个设定端口的服务,该服务用于向客户端传送主机的屏幕信息,实现客户端对服务器端主机的监控
* 实例化线程类后默认打开DEFAULT_SERVER_PORT=30011 端口实现监听
* 可以通过changeServerPort改变监听端口,也可以通过getServerPort来查询当前监听端口
*/

class SendScreenImg implements Runnable{ 


 public static final int DEFAULT_SERVER_PORT=30011; 

 private int serverPort; 

 private Robot robot; 

 private ServerSocket serverSocket; 

 private Rectangle rect; 

 private Dimension screen; 

 private BufferedImage img; 

 private Socket socket; 

 private ZipOutputStream zip; 


 public SendScreenImg() { 

 this.serverPort=SendScreenImg.DEFAULT_SERVER_PORT; 


 try { 

 serverSocket = new ServerSocket(this.serverPort); 

 serverSocket.setSoTimeout(86400000); 

 } catch (IOException e1) { 

 e1.printStackTrace(); 

 } 


 try { 

 robot = new Robot(); 

 } catch (AWTException e) { 

 e.printStackTrace(); 

 } 

 screen = Toolkit.getDefaultToolkit().getScreenSize(); 

 rect = new Rectangle(screen); 


 } 

 public void changeServerPort(int serverPort){ 

 if(this.serverPort==serverPort)return; 

 this.serverPort=serverPort; 

 try { 

 this.serverSocket.close(); 

 } catch (Exception e) {} 

 try { 

 serverSocket = new ServerSocket(this.serverPort); 

 serverSocket.setSoTimeout(86400000); 

 } catch (IOException e1) { 

 e1.printStackTrace(); 

 } 

 } 

 public int getServerPort(){ 

 return this.serverPort; 

 } 


 public void run() { 

 while (true) { 

 try { 

 System.out.println("等待接收截屏信息"); 

 socket = serverSocket.accept(); 

 zip = new ZipOutputStream(new DataOutputStream(socket.getOutputStream())); 

 zip.setLevel(9);//为后续的 DEFLATED 条目设置压缩级别 压缩级别 (0-9) 

 try { 

 img = robot.createScreenCapture(rect); 

 zip.putNextEntry(new ZipEntry("test.jpg")); 

 ImageIO.write(img, "jpg", zip); 

 if(zip!=null)zip.close(); 

 System.out.println("被控端:connect"); 

 } catch (IOException ioe) { 

 System.out.println("被控端:disconnect"); 

 } 

 } catch (IOException ioe) { 

 System.out.println("错误1"); 

 } finally { 

 if (socket != null) { 

 try { 

 socket.close(); 

 } catch (IOException e) { 

 } 

 } 

 } 

 } 

 } 

}



/**
* @author LanXJ @doctime 2010-7-8
* 开启一个设定端口的服务,该服务用于接受客户端传来的操作字符串,实现对服务器端主机的操控
* 实例化线程类后默认打开DEFAULT_SERVER_PORT=30012 端口实现监听
* 可以通过changeServerPort改变监听端口,也可以通过getServerPort来查询当前监听端口

*/ 

class OperateWindow implements Runnable { 

 public static final int DEFAULT_SERVER_PORT=30012; 

 private int serverPort; 

 private ServerSocket serverSocket; 

 private Robot robot; 

 public OperateWindow() { 

 this.serverPort=OperateWindow.DEFAULT_SERVER_PORT; 

 try { 

 this.serverSocket = new ServerSocket(this.serverPort); 

 this.serverSocket.setSoTimeout(86400000); 

 } catch (IOException e) { 

 e.printStackTrace(); 

 } 

 try { 

 robot = new Robot(); 

 } catch (AWTException e) { 

 e.printStackTrace(); 

 } 

 } 

 public void changeServerPort(int serverPort){ 

 if(this.serverPort==serverPort)return; 

 this.serverPort=serverPort; 

 try { 

 this.serverSocket.close(); 

 } catch (Exception e) {} 

 try { 

 this.serverSocket = new ServerSocket(this.serverPort); 

 this.serverSocket.setSoTimeout(86400000); 

 } catch (Exception e) { 

 e.printStackTrace(); 

 } 

 } 

 public int getServerPort(){ 

 return this.serverPort; 

 } 


 public void run() { 

 while (true) { 

 try { 

 Socket socket = serverSocket.accept(); 

 //读取操作信息:120,200,InputEvent.BUTTON1_DOWN_MASK 全部是int类型 

 InputStream is = socket.getInputStream(); 

 int r; 

 String info = ""; 

 while ((r = is.read()) != -1) { 

 info += "" + (char) r; 

 } 

 System.out.println(info); 

 is.close(); 

 if (info != null) { 

 String s[] = info.trim().split(","); 

 if ("mouseClicked".equals(s[0].trim())) {//operateStr Model: mouseClicked,x,y,type 

 //由于加上单击事件后,鼠标按下并快速抬起 就设计到按下、抬起、单击 三个事件,将单击变为了双击 不合乎规范 所以 服务端并没有实现单击事件的监听,这里保留 不坐修改 

 int type = Integer.parseInt(s[s.length - 1].trim()); 

 if (s.length == 4) { 

 int x = Integer.parseInt(s[1].trim()); 

 int y = Integer.parseInt(s[2].trim()); 

 robot.mouseMove(x, y); 

 robot.mousePress(type); 

 robot.mouseRelease(type); 

 System.out.println("ClientINFO:MOUSE move to "+x+","+y+" AND execute TYPE IS click "+type); 

 } 

 }else if("mousePressed".equals(s[0].trim())){//operateStr Model: mousePressed,x,y,type 

 int type = Integer.parseInt(s[s.length - 1].trim()); 

 if (s.length == 4) { 

 int x = Integer.parseInt(s[1].trim()); 

 int y = Integer.parseInt(s[2].trim()); 

 robot.mouseMove(x, y); 

 robot.mousePress(type); 

 System.out.println("ClientINFO:MOUSE move to "+x+","+y+" AND execute TYPE IS press "+type); 

 } 

 }else if("mouseReleased".equals(s[0].trim())){//operateStr Model: mouseReleased,x,y,type 

 int type = Integer.parseInt(s[s.length - 1].trim()); 

 if (s.length == 4) { 

 int x = Integer.parseInt(s[1].trim()); 

 int y = Integer.parseInt(s[2].trim()); 

 robot.mouseMove(x, y); 

 robot.mouseRelease(type); 

 System.out.println("ClientINFO:MOUSE move to "+x+","+y+" AND execute TYPE IS release "+type); 

 } 

 }else if("mouseDragged".equals(s[0].trim())){//operateStr Model: mouseDragged,x,y,type 

 if (s.length == 4) { 

 int x = Integer.parseInt(s[1].trim()); 

 int y = Integer.parseInt(s[2].trim()); 

 robot.mouseMove(x, y); 

 System.out.println("ClientINFO:MOUSE move to "+x+","+y ); 

 } 

 }else if("mouseMoved".equals(s[0].trim())){ 

 if (s.length == 3) { 

 int x = Integer.parseInt(s[1].trim()); 

 int y = Integer.parseInt(s[2].trim()); 

 robot.mouseMove(x, y); 

 System.out.println("ClientINFO:MOUSE move to "+x+","+y); 

 } 

 }else if("keyPress".equals(s[0].trim())){ 

 if(s.length==2){ 

 int keycode=Integer.parseInt(s[1]); 

 robot.keyPress(keycode); 

 } 

 }else if("keyRelease".equals(s[0].trim())){ 

 if(s.length==2){ 

 int keycode=Integer.parseInt(s[1]); 

 robot.keyRelease(keycode); 

 } 

 }else if("keyTyped".equals(s[0].trim())){ 

 if(s.length==2){ 

 int keycode=Integer.parseInt(s[1]); 

 robot.keyPress(keycode); 

 robot.keyRelease(keycode); 

 } 

 } 

 } 

 } catch (IOException e) { 

 System.out.println("error1"); 

 } 

 } 

 } 

}




--------------------------Client类---------------------------------------

import java.awt.Dimension; 

import java.awt.Image; 

import java.awt.Toolkit; 

import java.awt.event.KeyAdapter; 

import java.awt.event.KeyEvent; 

import java.awt.event.MouseAdapter; 

import java.awt.event.MouseEvent; 

import java.awt.event.MouseMotionAdapter; 

import java.awt.event.WindowAdapter; 

import java.awt.event.WindowEvent; 

import java.io.DataInputStream; 

import java.io.IOException; 

import java.io.OutputStream; 

import java.net.Socket; 

import java.net.UnknownHostException; 

import java.util.concurrent.TimeUnit; 

import java.util.zip.ZipInputStream; 


import javax.imageio.ImageIO; 

import javax.swing.*; 


public class Client{ 

 public static void main(String args[]) { 


 ServerGUI sendOrder=new ServerGUI("127.0.0.1", "实时操控");//被监控电脑的ip地址 

 WriteGUI catchScreen=new WriteGUI(sendOrder); 

 catchScreen.changePort(30009);//现在可以修改获取主机屏幕信息要访问的端口号 

 new Thread(catchScreen).start();//启动线程 

 } 

}



/**

* @author LanXJ @doctime 2010-7-8 

 * 访问指定端口的服务,从服务器端读取图像流,生成(刷新)管理面板 

 * 默认访问的端口为DEFAULT_PORT=30011 端口, 

 * 可以通过changePort来改变访问端口,也可以通过getPort查看当前访问端口 

 * 实例化线程类时需要传入一个ServerGUI类型的辅助窗体对象 

 */ 

class WriteGUI extends Thread { 

 public static final int DEFAULT_PORT=30011; 

 private int port; 

 private ServerGUI rec; 


 /** 

 * @param rec 辅助窗体对象,可通过实例化获得 

 */ 

 public WriteGUI(ServerGUI rec) { 

 this.port=WriteGUI.DEFAULT_PORT; 

 this.rec = rec; 

 } 

 public void changePort(int port){ 

 this.port=port; 

 } 

 public int getPort(){ 

 return this.port; 

 } 

 public void run() { 

 while (rec.getBoo()) { 

 System.out.println((System.currentTimeMillis()/1000)%24%60); 

 Socket socket = null; 

 try { 

 socket = new Socket(rec.getIP(), this.port); 

 DataInputStream dis = new DataInputStream(socket.getInputStream()); 

 ZipInputStream zis = new ZipInputStream(dis); 

 Image image = null; 

 try { 

 zis.getNextEntry();// 读取下一个 ZIP 文件条目并将流定位到该条目数据的开始处 

 image = ImageIO.read(zis);// 把ZIP流转换为图片 

 rec.jlabel.setIcon(new ImageIcon(image)); 

 rec.scroll.setViewportView(rec.jlabel); 

 rec.validate(); 

 } catch (IOException ioe) {} 

 try{ 

// dis.close(); 

 zis.close(); 

 }catch (Exception e) {} 

 try { 

 TimeUnit.MILLISECONDS.sleep(50);// 接收图片间隔时间 

 } catch (InterruptedException ie) { 

 ie.printStackTrace(); 

 } 

 } catch (IOException ioe) { 

 } finally { 

 try { 

 socket.close(); 

 } catch (IOException e) {} 

 } 

 } 

 } 

}


/**
* @author LanXJ @doctime 2010-7-8
* 访问指定主机的指定端口,向主机发送实例化线程类时传入的操控命令,实现对该主机的操控
* 默认访问服务端口为DEFAULT_PORT=30012 端口,主机IP为实例化线程类时传入的IP
* 可以通过changePort和changeIP来修改访问的端口和主机
* 也可以通过setOperateStr来设置需要发送的操控命令
* 需要注意的是,修改访问端口或主机必须在线程启动之前修改,否则修改无效

*/ 

class SendOperate extends Thread { 

 public static int DEFAULT_PORT=30012; 

 private String ip; 

 private int port;// 30012 

 private String operateStr; 


 public SendOperate(String ip, String operateStr) { 

 this.ip = ip; 

 this.port = SendOperate.DEFAULT_PORT; 

 this.operateStr = operateStr; 

 } 

 public void setOperateStr(String operateStr){ 

 this.operateStr=operateStr; 

 } 

 public void changePort(int port){ 

 this.port=port; 

 } 

 public boolean changeIP(String ip){ 

 if(UtilServer.checkIp(ip)){ 

 this.ip=ip; 

 return true; 

 } 

 return false; 

 } 

 public int getPort(){ 

 return this.port; 

 } 

 public String getIP(){ 

 return this.ip; 

 } 

 public void run() { 

 if(this.operateStr==null||this.operateStr.equals("")){ 

 return; 

 } 

// if(this.operateStr.trim().startsWith("mouseMoved")){ 

// return; 

// } 

 try { 

 Socket socket = new Socket(this.ip, this.port); 

 OutputStream os = socket.getOutputStream(); 

 os.write((this.operateStr).getBytes()); 

 os.flush(); 

 socket.close(); 

 System.out.println("INFO: 【SendOperate】ip=" + this.ip + ",port=" + this.port + ",operateStr="" + this.operateStr + ""."); 

 } catch (UnknownHostException e) { 

 e.printStackTrace(); 

 } catch (IOException e) { 

 e.printStackTrace(); 

 } 

 } 


} 


/** 

 * @author LanXJ @doctime 2010-7-8 

 * 服务工具类 

 */ 

class UtilServer{ 

 public static boolean checkIp(String ip){ 

 if(ip==null)return false; 

 String []dps=ip.split("\."); 

 if(dps.length!=4&&dps.length!=6)return false; 

 boolean isIp=true; 

 for (int i = 0; i < dps.length; i++) { 

 try { 

 int dp=Integer.parseInt(dps[i]); 

 if(dp>255||dp< 0){ 

 throw new RuntimeException("error IP"); 

 } 

 } catch (Exception e) { 

 isIp=false; 

 break; 

 } 

 } 

 return isIp; 

 } 

} 

/** 

 * @author LanXJ @doctime 2010-7-8 

 * serverManage的辅助窗体,内部事件封装了sendOperate的实现 

 */ 

class ServerGUI extends JFrame { 

 private static final long serialVersionUID = 2273190419221320707L; 

 JLabel jlabel; 

 JScrollPane scroll; 

 private String ip; 

 private int port; 

 private boolean boo; 

 public boolean getBoo(){ 

 return this.boo; 

 } 

 public int getPort(){ 

 return this.port; 

 } 

 public void changePort(int port){ 

 this.port=port; 

 } 

 public String getIP(){ 

 return this.ip; 

 } 

 public boolean changeIP(String ip){ 

 if(UtilServer.checkIp(ip)){ 

 this.setTitle(this.getTitle().replace(this.ip, ip)); 

 this.ip=ip; 

 return true; 

 } 

 return false; 

 } 


 protected ServerGUI(String IP, String sub) { 

 this.boo = true; 

 this.ip = IP; 

 this.port=SendOperate.DEFAULT_PORT; 

 this.setTitle("远程监控--IP:" + IP + "--主题:" + sub); 

 this.jlabel = new JLabel(); 

 this.scroll = new JScrollPane(); 

 this.scroll.add(this.jlabel); 

 scroll.addMouseListener(new MouseAdapter() { 

 /*public void mouseClicked(MouseEvent e) {// getMousePosition() 

 super.mouseClicked(e); 

 //由于加上单击事件后,鼠标按下并快速抬起 就设计到按下、抬起、单击 三个事件,将单击变为了双击 

 //所以不实现单击监听 

 int x = (int) e.getX() + (int) ServerGUI.this.scroll.getHorizontalScrollBar().getValue(); 

 int y = (int) e.getY() + (int) ServerGUI.this.scroll.getVerticalScrollBar().getValue(); 

// int type = e.getModifiers();//e.BUTTON1_MASK 或 e.BUTTON2_MASK 或 e.BUTTON3_MASK 

 String operateStr ="mouseClicked,"+ x + "," + y + "," + e.getModifiers(); 


 SendOperate sender=new SendOperate(ServerGUI.this.ip, (operateStr)); 

 sender.changeIP(ServerGUI.this.ip);//同步ip 

 sender.changePort(ServerGUI.this.port);//同步port 

 sender.start(); 

 }*/ 


 public void mousePressed(MouseEvent e) { 

 super.mousePressed(e); 

 int x = (int) e.getX() + (int) ServerGUI.this.scroll.getHorizontalScrollBar().getValue(); 

 int y = (int) e.getY() + (int) ServerGUI.this.scroll.getVerticalScrollBar().getValue(); 

// int type = e.getModifiers();//e.BUTTON1_MASK 或 e.BUTTON2_MASK 或 e.BUTTON3_MASK 

 String operateStr ="mousePressed,"+ x + "," + y + "," + e.getModifiers(); 


 SendOperate sender=new SendOperate(ServerGUI.this.ip, (operateStr)); 

 sender.changeIP(ServerGUI.this.ip);//同步ip 

 sender.changePort(ServerGUI.this.port);//同步port 

 sender.start(); 

 } 

 @SuppressWarnings("static-access") 

 public void mouseReleased(MouseEvent e) { 

 super.mouseReleased(e); 

 int x = (int) e.getX() + (int) ServerGUI.this.scroll.getHorizontalScrollBar().getValue(); 

 int y = (int) e.getY() + (int) ServerGUI.this.scroll.getVerticalScrollBar().getValue(); 

// int type = e.getModifiers();//e.BUTTON1_MASK 或 e.BUTTON2_MASK 或 e.BUTTON3_MASK 

 String operateStr ="mouseReleased,"+ x + "," + y + "," + e.getModifiers(); 


 SendOperate sender=new SendOperate(ServerGUI.this.ip, (operateStr)); 

 sender.changeIP(ServerGUI.this.ip);//同步ip 

 sender.changePort(ServerGUI.this.port);//同步port 

 sender.start(); 

 } 

 }); 

 scroll.addMouseMotionListener(new MouseMotionAdapter(){ 

 public void mouseDragged(MouseEvent e) { 

 super.mouseDragged(e); 

 int x = (int) e.getX() + (int) ServerGUI.this.scroll.getHorizontalScrollBar().getValue(); 

 int y = (int) e.getY() + (int) ServerGUI.this.scroll.getVerticalScrollBar().getValue(); 

 String operateStr ="mouseDragged,"+ x + "," + y + "," + e.getModifiers(); 


 SendOperate sender=new SendOperate(ServerGUI.this.ip, operateStr); 

 sender.changeIP(ServerGUI.this.ip);//同步ip 

 sender.changePort(ServerGUI.this.port);//同步port 

 sender.start(); 

 } 

 public void mouseMoved(MouseEvent e) { 

 super.mouseMoved(e); 

 int x = (int) e.getX() + (int) ServerGUI.this.scroll.getHorizontalScrollBar().getValue(); 

 int y = (int) e.getY() + (int) ServerGUI.this.scroll.getVerticalScrollBar().getValue(); 

 String operateStr ="mouseMoved,"+ x + "," + y; 


 SendOperate sender=new SendOperate(ServerGUI.this.ip, (operateStr)); 

 sender.changeIP(ServerGUI.this.ip);//同步ip 

 sender.changePort(ServerGUI.this.port);//同步port 

 sender.start(); 

 } 

 }); 

 this.addKeyListener(new KeyAdapter(){ 

 public void keyPressed(KeyEvent e) { 

 super.keyPressed(e); 

 String operateStr ="keyPress,"+ e.getKeyCode(); 


 SendOperate sender=new SendOperate(ServerGUI.this.ip, (operateStr)); 

 sender.changeIP(ServerGUI.this.ip);//同步ip 

 sender.changePort(ServerGUI.this.port);//同步port 

 sender.start(); 

 } 

 public void keyReleased(KeyEvent e) { 

 super.keyReleased(e); 

 String operateStr ="keyReleas,"+ e.getKeyCode(); 


 SendOperate sender=new SendOperate(ServerGUI.this.ip, (operateStr)); 

 sender.changeIP(ServerGUI.this.ip);//同步ip 

 sender.changePort(ServerGUI.this.port);//同步port 

 sender.start(); 

 } 

 public void keyTyped(KeyEvent e) { 

// super.keyTyped(e); 

 } 

 }); 

 this.add(scroll); 


 this.setAlwaysOnTop(false); 

 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 

 this.setBounds(100, 75, (int) screenSize.getWidth() - 200, (int) screenSize.getHeight() - 150); 

 // this.setResizable(false); 

 this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);// 关闭窗体不做任何事 

 this.addWindowListener(new WindowAdapter() { 

 public void windowClosing(WindowEvent e) { 

 boo = false; 

 ServerGUI.this.dispose(); 

 System.out.println("窗体关闭"); 

 System.gc(); 

 } 

 }); 

 this.setVisible(true); 

 this.validate(); 


 } 


}



[color=red][b]推荐软件[/b][/color]

用java开发的一款功能强大的开源的远程控制软件,最近又升级了,添加了许多使用的功能,而且代码也有了很大程度的优化。可以实现[b]生成服务器、修改上线主机名称、屏幕监视,屏幕控制、主动连接、上传文件、下载文件、 远程命令、远程任务管理器、发送警告、相互聊天、换皮肤、版本升级提醒[/b]等功能,通过该软件可以实现用一台电脑同时控制多台电脑,也可以多台电脑控制同一台电脑等。
[b]软件官方网站下载地址:[url]http://dl.iteye.com/topics/download/c1b7acd2-c7ad-3753-8929-48424025d711[/url][/b]

软件如下图所示:

[img]http://dl.iteye.com/upload/attachment/605144/8161a553-ddf6-3758-b4f5-e4469ad8b403.jpg[/img]