java实现远程桌面

java实现远程桌面

控制端将鼠标事件传递到服务端
服务端拿到鼠标事件之后传输到客户端
客户端拿到鼠标事件之后,通过robot类即可完成,并且截屏将图片发给服务器,服务器再发给控制端

java实现远程桌面_第1张图片

被我简化之后得到

java实现远程桌面_第2张图片


//先介绍一下robot类的简单使用
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;

/**
 * 使用robot
 * @author 哑元
 *
 */
public class RobotTest {
    public static void main(String[] args) throws AWTException {
        Robot r = new Robot();
        r.mouseMove(300, 500);//鼠标移动
        r.mousePress(InputEvent.BUTTON1_MASK ); //鼠标按下
        r.mouseRelease(InputEvent.BUTTON1_MASK);//鼠标松开
        r.keyPress((int)'A');   //键盘按下  (int)'A'表示将A转换成键盘对应的key
        r.keyRelease((int)'A'); //键盘松开
    }
}


//屏幕抓取
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;

/**
 * 抓取本地桌面图片
 * @author 哑元
 *
 */
public class ScreenTest {
    public static void main(String[] args) throws AWTException, InterruptedException {
        Robot robot = new Robot();  
        JFrame jframe = new JFrame();
        jframe.setSize(1200, 700);
        JLabel label = new JLabel();
        jframe.add(label);
        //四个参数x y width height
        jframe.setVisible(true);
        jframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE );
        //构建一个死循环动态截取
        while(true){
            BufferedImage image = robot.createScreenCapture(new Rectangle(0,0,1366,768));//截取屏幕
            label.setIcon(new ImageIcon(image));
            Thread.sleep(50);
        }   
    }

}

//远程控制原理讲解
//分为server端和client端,
//原本server端只作为转发,作为演示,就不写转发
//也就是client端控制server端E
/**
* 这里我采用的是,在client端也就是操控端,接收到server端发送过来的screen之后,然后发送鼠标事件过去
* 然后再用robot处理
* 传输方式用socket+io即可处理
* 屏幕截取和图片压缩采用了robot的屏幕截取功能和jdk自带的图片编码器,将其转换成一个字节数组
* 发送给server端之后,robot通过io+socket可以直接拿到object对象,强制转换成InputEvent(keyEvent和MouseEvent都继承)之后
* 通过判断event类型,分别处理即可,这里在服务端需要用到两个线程,一个是屏幕截取和发送给客户端,一个是用来监听客户端
* 传递过来的事件
*/

//下面是具体实现代码


//server主程
import java.awt.AWTException;
import java.awt.Event;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务端
 * @author 哑元
 *
 */
public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(80);
        System.out.println("服务器已经正常启动");
        Socket socket = server.accept();//等待接收请求,阻塞方法
        System.out.println("有客户端连接");
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
        //将客户端与服务器端链接的输出流交个ImageThread处理
        ImageThread imageThread = new ImageThread(dos);
        new Thread(imageThread).start();
        new Thread(new EventThread(new ObjectInputStream(socket.getInputStream()))).start();
    }
}
/**
 * 用来处理接收过来的鼠标事件或者键盘事件
 */
class EventThread implements Runnable{
    private ObjectInputStream ois;
    private Robot robot;
    public EventThread(ObjectInputStream ois) {
        this.ois = ois;
    }
    @Override
    public void run() {
        try {
            robot = new Robot();
            while(true){
                InputEvent event = (InputEvent)ois.readObject();//得知由客户端传递过来的是一个object对象
                actionEvent(event);//处理事件
            }
        } catch (AWTException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    /**
     * 事件处理,用来判断事件类型,并用robot类执行
     * @param event
     */
    public void actionEvent(InputEvent event){
        System.out.println(event);
        if(event instanceof KeyEvent){
            KeyEvent e = (KeyEvent)event;
            int type = e.getID();//拿到事件类型
            if(type==Event.KEY_PRESS){
                robot.keyPress(e.getKeyCode());
            }else if(type == Event.KEY_RELEASE){
                robot.keyRelease(e.getKeyCode());
            }
        }else if(event instanceof MouseEvent){
            MouseEvent e = (MouseEvent)event;
            int type = e.getID();
            if(type == Event.MOUSE_MOVE){
                robot.mouseMove(e.getX(),e.getY());
            }else if(type == Event.MOUSE_DOWN){
                robot.mousePress(getMouseKey(type));
            }else if(type == Event.MOUSE_UP){
                robot.mouseRelease(getMouseKey(type));
            }else if(type == Event.MOUSE_DRAG){
                robot.mouseMove(e.getX(), e.getY());//鼠标拖动
            }
        }
    }
    /**
     * 返回鼠标的真正事件,鼠标时间不能直接处理,需要进过转换
     * @return
     */
    public int getMouseKey(int button){
        if(button == MouseEvent.BUTTON1){//鼠标左键
            return InputEvent.BUTTON1_MASK;
        }else if(button == MouseEvent.BUTTON2){//鼠标右键
            return InputEvent.BUTTON2_MASK;
        }else if(button == MouseEvent.BUTTON3){//滚轮
            return InputEvent.BUTTON3_MASK;
        }else{
            return 0;
        }
    }

}


//屏幕截取器和发送器,这里需要拿到socket的out流
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.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import com.sun.image.codec.jpeg.*;
/**
 * 用来将图片数据发送
 * @author 哑元
 *
 */
public class ImageThread implements Runnable{
    DataOutputStream dos = null;    //数据输出流
    public ImageThread(DataOutputStream dos){
        this.dos = dos;
    }
    @Override
    public void run() {
        try {
            Robot robot = new Robot();
            //截取整个屏幕
            Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
            /*
            int width = (int)dimension.getWidth();
            int height = (int)dimension.getWidth();
            Rectangle rec = new Rectangle(0,0,width,height);
            */
            Rectangle rec = new Rectangle(dimension);
            BufferedImage image;
            byte imageBytes[];
            while(true){
                image = robot.createScreenCapture(rec);
                imageBytes = getImageBytes(image);
                dos.writeInt(imageBytes.length);
                dos.write(imageBytes);
                dos.flush();
                Thread.sleep(50);   //线程睡眠
            }

        } catch (AWTException e) {
            e.printStackTrace();
        } catch (ImageFormatException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            try {
                if(dos!= null)  dos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     *  压缩图片
     * @param 需要压缩的图片
     * @return 压缩后的byte数组
     * @throws IOException 
     * @throws ImageFormatException 
     */
    public byte[] getImageBytes(BufferedImage image) throws ImageFormatException, IOException{
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        //压缩器压缩,先拿到存放到byte输出流中
        JPEGImageEncoder jpegd = JPEGCodec.createJPEGEncoder(baos);
        //将iamge压缩
        jpegd.encode(image);
        //转换成byte数组
        return baos.toByteArray();  
    }

}


--------------------------------------------------------------------------------------
//client端,用来接收creen图片和发送鼠标事件
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;

/**
 * 客户端
 * @author 哑元
 *
 */
public class Client {

    public static void main(String args[]) throws UnknownHostException, IOException{
        Socket s = new Socket("127.0.0.1",80);
        DataInputStream dis = new DataInputStream(s.getInputStream());
        ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
        ClientWindow cw = new ClientWindow(oos);
        byte[] imageBytes;
        while(true){
            imageBytes = new byte[dis.readInt()];   //先拿到传过来的数组长度
            dis.readFully(imageBytes);  //所有的数据存放到byte中
            cw.repainImage(imageBytes);
        }
    }
}

/**
 * 客户端窗体
 * @author 哑元
 *
 */
class ClientWindow extends JFrame{
    private ObjectOutputStream oos;
    private JLabel label;
    //重写背景图片方法
    public void repainImage(byte [] imageBytes){
        label.setIcon(new ImageIcon(imageBytes));
        this.repaint();
    }
    public ClientWindow(ObjectOutputStream oos){
        this.oos = oos;
        this.setTitle("远程控制程序");
        label = new JLabel();
        JPanel p = new JPanel();
        p.add(label);
        JScrollPane scroll = new JScrollPane(p);//给p面板添加滚动条
        this.add(scroll);
        this.setSize(1024,768);
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.setVisible(true);
        this.addKeyListener(new KeyListener() {

            @Override
            public void keyTyped(KeyEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void keyReleased(KeyEvent e) {
                sendEvent(e);

            }

            @Override
            public void keyPressed(KeyEvent e) {
                sendEvent(e);

            }
        });

        label.addMouseListener(new MouseListener() {

            @Override
            public void mouseReleased(MouseEvent e) {
                sendEvent(e);

            }

            @Override
            public void mousePressed(MouseEvent e) {
                sendEvent(e);

            }

            @Override
            public void mouseClicked(MouseEvent e) {
                sendEvent(e);

            }

            @Override
            public void mouseEntered(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseExited(MouseEvent e) {
                // TODO Auto-generated method stub

            }
        });
    }
    public void sendEvent(InputEvent event){
        try {
            oos.writeObject(event);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

你可能感兴趣的:(java)