远程控制(RemoteControl)

远程控制的基本原理... 2

远程控制(RemoteControl)拥有控制端和被控端双方...2

事件回放原理... 2

捕获桌面原理:... 3

远程控制(RemoteControl)的核心技术5

1 、Socket编程...  5

2、控制端事件的封装... 5

3、画面的传输... 6

远程控制(RemoteControl)的控制端...7

远程控制(RemoteControl)的被控制端15

远程控制(RemoteControl)的界面截图25

控制端(客户端)... 25

被控制端(远端或服务端)...  25


远程控制的基本原理
远程控制(RemoteControl)拥有控制端和被控端双方。
控制方通过请求,取得对远端的操作,实现远端的事件回放功能,同时,应该看得到远端桌面的画面。
而被控方必须在建立ServerSocket之后进行对外来请求的鉴听。如下图,
事件回放原理
利用JAVA.AWT.ROBOT类,实现在远端的回放功能
例子:// Robot使用示例
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
publicclass RobotTest {
 
 publicstaticvoid main(String[]args)throws Exception {
// 创建一个机器人对象
 java.awt.Robot robot = new java.awt.Robot();
 //当前屏幕大小
 Toolkit tk = java.awt.Toolkit.getDefaultToolkit();
 java.awt.Dimension dm = tk.getScreenSize();
 //计算屏幕中心点
 int x = (int) dm.getWidth() / 2;
 int y = (int) dm.getHeight() / 2;
// 将鼠标移动到屏幕中心
 
// 按下鼠标左键
 robot.mousePress(InputEvent.BUTTON1_MASK);
// 松开鼠标左键
 robot.mouseRelease(InputEvent.BUTTON1_MASK);
// 模拟按下回车键
 robot.keyPress(KeyEvent.VK_ENTER);
//  模拟放松回车键
 robot.keyRelease(KeyEvent.VK_ENTER);
// 按下SHIFT键
 robot.keyPress(KeyEvent.VK_SHIFT);
 for (int i = 0; i < 10; i++) {
// 在屏幕上打字
 robot.keyPress('A' + i);
 robot.keyRelease('A' + i);
 Thread.sleep(500);
 }
// 松开SHIFT键
 robot.keyRelease(KeyEvent.VK_SHIFT);
 for (int i = 0; i < 11; i++) {
// 删除操作
 robot.keyPress(KeyEvent.VK_BACK_SPACE);
 robot.keyRelease(KeyEvent.VK_BACK_SPACE);
 Thread.sleep(500);
 }
 }
}
捕获桌面原理:
同样利用ROBOT里的createScreenCapture()方法进行画面的捕获。
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import javax.swing.*;
publicclass ScreenTest {
 //  截屏测试
 publicstaticvoid main(String[] args)throws Exception {
 //控制台标题
 JFrame jf = new JFrame("控制台");
//控制台大小
 jf.setSize(500, 400);
//imag_lab用于存放画面
 JLabel imag_lab = new JLabel();
 jf.add(imag_lab);
//设置控制台可见
 jf.setVisible(true);
//控制台置顶
 jf.setAlwaysOnTop(true);
//控制台退出模式
 jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 java.awt.Dimension d =jf.size();
 java.awt.Graphics g = jf.getGraphics();
 //当前屏幕大小
 Toolkit tk = java.awt.Toolkit.getDefaultToolkit();
 java.awt.Dimension dm =tk.getScreenSize();
 
 //创建Robot对象
 java.awt.Robot robot = new java.awt.Robot();
 for (int i = 0; i < 1000; i++) {
 //截取指定大小的屏幕区域
 Rectangle rec = new Rectangle(0, 0, (int) dm.getWidth(), (int) dm
 .getHeight());
 BufferedImage bimage = robot.createScreenCapture(rec);
 //将图片转为小图片
 BufferedImage littleImage =resize(bimage,jf.getWidth(),jf
 .getHeight());
 //将图片保存到文件中
 FileOutputStream fous =new FileOutputStream("screenImg”+i+”.jpeg");
 //javax.imageio.ImageIO.write(littleImage, "jpeg", fous);
 fous.flush();
 fous.close();
 //将小图片显示到界面上
 imag_lab.setIcon(new javax.swing.ImageIcon(littleImage));
 Thread.sleep(50);
 }
 }
 
 privatestatic BufferedImage resize(BufferedImage img,int newW,int newH) {
 int w = img.getWidth();
 int h = img.getHeight();
 BufferedImage dimg = new BufferedImage(newW, newH, img.getType());
 Graphics2D g = dimg.createGraphics();
 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
 RenderingHints.VALUE_INTERPOLATION_BILINEAR);
 g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h,null);
 g.dispose();
 return dimg;
 }
}
远程控制(RemoteControl)的核心技术
1 、Socket编程
 利用JAVA Socket编程,使控制端与被控端之间建立数据传输的数据流通道。
例子:
(远端)ServerSocketss =new ServerSocket(PORT);
Socket client = ss.accept();
(近端)Socket s=new Socket(IP,PORT);
注:Socket有对应的输入输出(InputStream、 OutputStream)流对象。
2、控制端事件的封装
将控制端所侦听到的事件封装成InputEvent类,用对像输入出流,往远端写出去。
 privatevoidsendEventObject(java.awt.event.InputEventevent){
 
 try{
//将事件对象发送到被控制端
 ous.writeObject(event);
 }catch(Exception ef){
 ef.printStackTrace();
 }
 
 }
3、画面的传输
在远端,每隔一段一定的时间,将从桌面捕获的画面图片,用javax.io.ImagIO转成一个字节数组,从而将每一个画面的数据量大小,以及数据用数据输出流往控制端发送。
相关代码:
 publicvoid run(){
 //截图,发送
 try{
 while(true){
 byte[] data=createImage();
 //发送:
   //1.先写一个int ,代表图片数据长度
 dous.writeInt(data.length);
   //2.写入图片字节数据
 dous.write(data);
 dous.flush();
 Thread.sleep(1000/20);
 }
 }catch(SocketExceptionef){
// ef.printStackTrace();
 rs.destroy();
 thrownew MyException("客户端SOCKET已断开连接,无法发送图片信息。。");
 
 } catch(InterruptedException e) {
 //TODO Auto-generatedcatch block
 rs.destroy();
 thrownew MyException("客户端已中断连接,无法发送图片信息。。");
 } catch (IOException e) {
 //TODO Auto-generatedcatch block
 rs.destroy();
 thrownew MyException("客户端输入输出流中断,无法发送图片信息。。");
 } catch (Exception e) {
 //TODO Auto-generatedcatch block
 rs.destroy();
 thrownew MyException("客户端已断开连接,无法发送图片信息。。");
 }
 }
 
 //取得一张屏幕图片,转成字节数组返回
 privatebyte[] createImage()throws Exception{
 java.awt.Robot robot=new java.awt.Robot();
 java.awt.Toolkit tk=java.awt.Toolkit.getDefaultToolkit();
 
 //设定区域的大小
 Rectangle rt=new Rectangle(0,0,dm.width,dm.height);
 //取得指定大小的一张图片
 BufferedImage image=robot.createScreenCapture(rt);
 //创建一段内存流
 
 java.io.ByteArrayOutputStreamtemB=newByteArrayOutputStream();
 //将图片数据写入内存流中
 javax.imageio.ImageIO.write(image,"jpeg", temB);
 //做为字节数组返回
 byte[] data=temB.toByteArray();
 return data;
 }
远程控制(RemoteControl)的控制端 
在控制端,实现对所有事件(Mouse、Key)的侦听,将所有事件封装在InputEvent类,并用对像输出流ObjectOutputStream发送到远端。同时,控制端为一个线程,不断地执行run()方法,将接收到的画面数据(按远端转成字节数据的逆过程)转成图片,并在控制端显示。
控制端代码(在包com.zzw.client里有三个类,代码分别如下)
package com.zzw.client;


importjava.awt.FlowLayout;
import java.awt.event.*;

import javax.swing.*;

importjava.net.InetAddress;
importjava.net.UnknownHostException;
public class Client extends JFrame {

 /**
 * @param args
 */
 public JTextField iptf =new JTextField(10);
 public JTextField porttf =new JTextField(3);
 public JButton jb1 = new JButton("连接");
 public JButton jb2 = new JButton("断开");
 public void launch(){


 this.setTitle("远程控制客户端---连接窗口");
 this.setLocation(300, 200);
 this.setSize(300, 100);
 this.setAlwaysOnTop(true);

 JLayeredPane jlp =new JLayeredPane();
 jlp.setLayout(new FlowLayout());

 jlp.add(new JLabel("远程IP地址:"));
 iptf.setText("127.0.0.1");
 porttf.setText("8888");
 jlp.add(iptf);
 jlp.add(new JLabel("端口:"));
 jlp.add(porttf);
 jb1.addMouseListener(new MouseAdapter(){


 public void mouseClicked(MouseEvent e) {

 try {

 ClientDealObject.connect(iptf.getText(),Integer.parseInt(porttf.getText().trim()));

 } catch (NumberFormatException e1) {
 //端口号格式输入出错
 JOptionPane.showMessageDialog(null,"IP地址或端口号输入出错,无法取得连接。。","提示",JOptionPane.ERROR_MESSAGE);
 System.exit(0);
 destroy();
// 
 } catch (MyException e1) {
// JOptionPane.showMessageDialog(null,e1.info,"提示",JOptionPane.ERROR_MESSAGE);

// 
 }catch(Exception ed){
 // "远程不允许被控,无法取得连接。。
 JOptionPane.showMessageDialog(null,"远程不允许被控,无法取得连接。。","提示",JOptionPane.ERROR_MESSAGE);
 System.exit(0);
 destroy();
 }
 //连接成功 



 }

 });
 jb2.addMouseListener(new MouseAdapter(){


 public void mouseClicked(MouseEvent e) {
 JOptionPane.showMessageDialog(null, "断开控制端窗口","提示",JOptionPane.INFORMATION_MESSAGE);
 System.exit(0);
 destroy();
 }

 });
 jlp.add(jb1);
 jlp.add(jb2);
 this.setLayeredPane(jlp);
 this.addWindowListener(new WindowAdapter(){

 public void windowClosing(WindowEvent e) {
 // 关闭窗口
 JOptionPane.showMessageDialog(null, "关闭连接窗口","提示",JOptionPane.INFORMATION_MESSAGE);
 System.exit(0);

 } 

 });

 this.setVisible(true);


 }
 public static void main(String[] args) {
 // TODO Auto-generated method stub
// new RemoteControlLoginFrame().getLocalIP();
 new Client().launch();
 }

 public String getLocalIP(){
 String ipstr = "";
 InetAddress ip = null;
 try {
 ip = InetAddress.getLocalHost();
 } catch (UnknownHostException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 ipstr = ip.toString();
 ipstr = ipstr.substring(ipstr.indexOf("/")+1);
 System.out.println(ipstr);
 return ipstr;
 }
 public void destroy(){
 this.destroy();
 }



}


///
package com.zzw.client;


import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
importjava.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
importjava.io.ByteArrayInputStream;
importjava.io.DataInputStream;
importjava.io.ObjectOutputStream;

importjavax.imageio.ImageIO;
importjavax.swing.ImageIcon;
importjavax.swing.JLayeredPane;

public class ClientDealObject
 public int x,y;
 private java.io.DataInputStream dins;
 private java.io.ObjectOutputStream ous;
 private javax.swing.JLabel la_image=new javax.swing.JLabel();

 public void showUI(){
 javax.swing.JFrame frame=new javax.swing.JFrame("远程控制");
 frame.setSize(800,600);
 frame.setResizable(false);
 la_image.setSize(800, 600);

 JLayeredPane jlp = new JLayeredPane();
 jlp.add(la_image);

 frame.setLayeredPane(jlp);


 frame.setVisible(true);
 frame.setDefaultCloseOperation(3);
 frame.setAlwaysOnTop(true);

 frame.addKeyListener(new KeyAdapter(){

 public void keyPressed(KeyEvent e) {
 sendEventObject(e);
 }

 @Override
 public void keyReleased(KeyEvent e) {
 sendEventObject(e);
 }

 @Override
 public void keyTyped(KeyEvent e) {

 }

 });

 frame.addMouseWheelListener(new MouseWheelListener(){
 public void mouseWheelMoved(MouseWheelEvent e) {

 sendEventObject(e);

 }

 });
 frame.addMouseMotionListener(new MouseMotionListener(){

 public void mouseDragged(MouseEvent e) {

 sendEventObject(e);
 }

 public void mouseMoved(MouseEvent e) {


 sendEventObject(e);

 }



 });
 frame.addMouseListener(new MouseListener(){

 public void mouseClicked(MouseEvent e) {

 sendEventObject(e);

 }


 public void mouseEntered(MouseEvent e) {

 sendEventObject(e);
 }


 public void mouseExited(MouseEvent e) {

 sendEventObject(e);
 }


 public void mousePressed(MouseEvent e) {

 sendEventObject(e);
 }


 public void mouseReleased(MouseEvent e) {

 sendEventObject(e);
 }

 });



 }

 private void conn2Server(String ip,int port)
 throws MyException,Exception{
 java.net.Socket sc=new java.net.Socket(ip,port);
 dins=newDataInputStream(sc.getInputStream());

 ous=newObjectOutputStream(sc.getOutputStream());

 if(dins==null||ous==null)throw newMyException("远程控制不接受或未接受被控制。。。");
 }

 //发送事件对象到被控制端
 private void sendEventObject(java.awt.event.InputEvent event){

 try{
 ous.writeObject(event); 
 }catch(Exception ef){
 ef.printStackTrace();
 }

 }


 public void run(){
 try{

 while(true){
 int len=dins.readInt();
 byte[] data=new byte[len];
 dins.readFully(data);
 ByteArrayInputStream bins=newByteArrayInputStream(data);
 BufferedImage image= ImageIO.read(bins);
 javax.swing.ImageIcon ic=new ImageIcon(image);

 Image img = ic.getImage();
 Toolkit tk = Toolkit.getDefaultToolkit() ;
 Dimension d =tk.getScreenSize();

 int w = d.width;
 int h =d.height;
 BufferedImage bi = resize(img,800,600);


 la_image.setIcon(new ImageIcon(bi));
 la_image.repaint();//销掉以前画的背景

 }
 }catch(Exception ef){
 System.out.println("网络故障:无法读出远程图片数据。。。");
 ef.printStackTrace();
 }

 }

 private static BufferedImage resize(Image img, int newW, intnewH) {
 int w = img.getWidth(null);
 int h = img.getHeight(null);
 BufferedImage dimg = new BufferedImage(newW, newH,BufferedImage.TYPE_INT_BGR);
 Graphics2D g = dimg.createGraphics();
 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
 RenderingHints.VALUE_INTERPOLATION_BILINEAR);
 g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h, null);
 g.dispose();
 return dimg;
 }


 public static void main(String[] args)
 throws Exception{


 }
 public static void connect(String ip,intport) throws Exception{
 ClientDealObject ct=newClientDealObject();
 ct.showUI();
 ct.conn2Server(ip,port);

 ct.start();
 }

}
package com.zzw.client;

import javax.swing.JOptionPane;

public classMyException extendsRuntimeException {
 public String info= "";
 public MyException(String info){
 this.info = info;
 System.out.println(info);
 JOptionPane.showMessageDialog(null, this.info,"提示",JOptionPane.ERROR_MESSAGE);
 }
}