当前位置 主页 > 服务器问题 > win服务器问题汇总 >

    java实现远程桌面的实例代码

    栏目:win服务器问题汇总 时间:2019-10-09 10:55

    java实现远程桌面的实例代码

    控制端将鼠标事件传递到服务端

    服务端拿到鼠标事件之后传输到客户端

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

    被我简化之后得到

    //先介绍一下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();
      }
     }
    }