Java implements remote control technology
A mix of java.net and java.awt.robot., which come with java, can be used to realize remote control of another computer over the network, including controlling the movement of the remote computer mouse and input of the keyboard, and obtaining images of the remote computer screen in real time. This article will use concise language and logic from shallow to deep to teach you how to master this technique.
First, let’s take a look at the renderings:
Remote computer interface:
Control terminal computer interface:
Control terminal input:
Remote input:
Let’s start with the detailed introduction of the technical ideas of remote control.
First, the two computers are connected through the Socket of java.net.
First open a ServerSocket on one end, and then connect with the other end with a socket.
Server side
A ServerSocket should be set up and the input and output streams that are required are initialized:
public static void OpenServer() throws IOException, ClassNotFoundException{ System.out.println("ServerStart......"); ServerSocket server = new ServerSocket(7777); socket = server.accept(); System.out.println("on connection.../n"+socket); OIS = new ObjectInputStream(socket.getInputStream()); OOS=new ObjectOutputStream(socket.getOutputStream()); }Client side <br />The socket should be used to connect to the server and initialize the input and output stream:
public static void StartConnection(String IP,int port) throws UnknownHostException, IOException, AWTException{ socket = new Socket("192.168.0.106",7777); if(socket.isConnected()){ System.out.println("socket connected..."+socket); } OOS = new ObjectOutputStream(socket.getOutputStream()); OIS = new ObjectInputStream(socket.getInputStream()); }In this way, the two computers are linked together and data can be exchanged through streams (InputStream and OutputStream).
Next, you can think about what information do two computers need to exchange for remote control? First, the controlled end needs to continuously provide the screen image to the control end (this will be implemented using java.awt.robot), and then the mouse and keyboard do the same operation based on the event (inputEvent) transmitted by the control end (implemented using robot). Then the control end must first receive the image transmitted by the controlled end and reflect it on a panel (pane), then monitor the actions of the keyboard and mouse on the machine and then pass it to the host of the controlled end (we can do it by setting a listener on the panel pane)
One problem encountered here is that the images used for transmission cannot be serialized whether they are using image or bufferedImage. Therefore, I/OStream cannot be used for transmission. Therefore, in order to solve this problem, we need to encapsulate the image data in a class and implements the Serializable interface image class as follows:
import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.Serializable;public class Message implements Serializable { private static final long serialVersionUID = 1L; private String fileName; // File name private long fileLength; // File length private byte[] fileContent; // File content public Message(){ } public Message(String filePath) throws IOException{ File file = new File(filePath); this.fileLength=file.length(); this.fileName=file.getName(); FileInputStream FIS = new FileInputStream(filePath); byte[] bytes = new byte[(int)fileLength]; FIS.read(bytes,0,(int)fileLength); this.fileContent=bytes; } public String getFileName() { return fileName;} public void setFileName(String fileName) { this.fileName = fileName;} public long getFileLength() { return fileLength; } public void setFileLength(long fileLength) {this.fileLength = fileLength;} public byte[] getFileContent() {return fileContent;} public void setFileContent(byte[] fileContent) {this.fileContent = fileContent;}}This enables the image to be propagated through serialization of ObjectInputStream and ObjectOutputStream
After understanding the above basics, we must first complete the UI interface setting, image reception, and keyboard and mouse action monitoring of the control side:
First, set up the receiving picture:
public static void reveivePic() throws ClassNotFoundException, IOException{ Message g = (Message)OIS.readObject(); FileOutputStream FOS = new FileOutputStream("D://OUT//"+g.getFileName()); FOS.write(g.getFileContent(),0,(int)g.getFileLength()); FOS.flush(); FileInputStream FIS= new FileInputStream("D://OUT//"+g.getFileName()); BufferedImage BI = ImageIO.read(FIS); IIC=new ImageIcon(BI); Image img = IIC.getImage(); Toolkit tk = Toolkit.getDefaultToolkit(); Dimension d =tk.getScreenSize(); int w = d.width; int h =d.height; BufferedImage bi = resize(img,800,600); image_lab.setIcon(new ImageIcon(bi)); img_lab.repaint();//Pind away the background I drew before} private static BufferedImage resize(Image img, int newW, int newH) { 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; }In this way, after receiving the Message class from ObjectInputStream, the image can be reset to the size of the panel pane and displayed
The next step is to set panel properties and listeners:
public static void showUI(){ //Console title JFrame jf = new JFrame("Console"); setListener(jf); //Console size jf.setSize(500, 400); //imag_lab is used to store the picture imag_lab = new JLabel(); jf.add(imag_lab); //Setvisible(true); //Console top jf.setAlwaysOnTop(true); jf.setResizable(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); }Listener:
public static void setListener( JFrame frame){ //panel set listener 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 static void sendEventObject(InputEvent event){ try{ System.out.println("send"); OOS.writeObject(event); OOS.flush(); }catch(Exception ef){ ef.printStackTrace(); }The above completes the control end.
Next we will build the controlled end:
The controlled end needs to use robot to take screenshots and send, and it is necessary to write a method to react to the received InputEvent first: the screenshots and sends:
public static void CapturePic() throws AWTException, IOException{ robot= new Robot(); Message msg = null; Toolkit tk = java.awt.Toolkit.getDefaultToolkit(); java.awt.Dimension dm =tk.getScreenSize(); java.awt.Robot robot = new java.awt.Robot(); for (int i = 0; i < 50; i++) { //Intercept the screen area of the specified size Rectangle rec = new Rectangle(0, 0, (int) dm.getWidth(), (int) dm .getHeight()); BufferedImage bimage = robot.createScreenCapture(rec); //Save the image to a file String filePath = "D://OUT//screenshot"+i+".jpeg"; FileOutputStream fops = new FileOutputStream(filePath); javax.imageio.ImageIO.write(bimage, "jpeg", fops); fops.flush(); fops.close(); msg =new Message(filePath); System.out.println(msg.getFileName()); System.out.println("send"); OOS.writeObject(msg); OOS.flush(); } }Note that this code uses the D:/OUT/ directory as the storage place for temporary files. Readers need to set the storage of temporary documents by themselves when using this code.
Then implement robot to operate on the received InputEvent instruction:
public void action() throws AWTException, ClassNotFoundException, IOException{ Robot robot= new Robot(); while(true){ InputEvent e =(InputEvent)OIS.readObject(); if(e!=null){ handleEvents(robot,e);} } } public static void handleEvents(Robot action,InputEvent event){ MouseEvent mevent = null ; //Mouse event MouseWheelEvent mwevent = null ;//Mouse scroll event KeyEvent kevent = null ; //Keyboard event int mousebuttonmask = -100; //Mouse key switch (event.getID()){ case MouseEvent.MOUSE_MOVED : //Mouse movement mevent = ( MouseEvent )event ; action.mouseMove( mevent.getX() , mevent.getY() ); break ; case MouseEvent.MOUSE_PRESSED : //Mouse key press mevent = ( MouseEvent ) event; action.mouseMove( mevent.getX() , mevent.getY() ); mousebuttonmask = getMouseClick(mevent.getButton() ); if(mousebuttonmask != -100) action.mousePress(mousebuttonmask); break; case MouseEvent.MOUSE_RELEASED : //Release the mouse button mevent = ( MouseEvent ) event; action.mouseMove( mevent.getX() , mevent.getY() ); mousebuttonmask = getMouseClick( mevent.getButton() ); //Get the mouse button if(mousebuttonmask != -100) action.mouseRelease( mousebuttonmask ); break ; case MouseEvent.MOUSE_WHEEL : //Mouse scroll mwevent = ( MouseWheelEvent ) event ; action.mouseWheel(mwevent.getWheelRotation()); break ; case MouseEvent.MOUSE_DRAGGED : //Mouse drag mevent = ( MouseEvent ) event ; action.mouseMove( mevent.getX(), mevent.getY() ); break ; case KeyEvent.KEY_PRESSED : //Key kevent = ( KeyEvent ) event; action.keyPress( kevent.getKeyCode() ); break ; case KeyEvent.KEY_RELEASED : //Solved key kevent= ( KeyEvent ) event ; action.keyRelease( kevent.getKeyCode() ); break ; default: break ; } } private static int getMouseClick(int button) { //Get the mouse button if (button == MouseEvent.BUTTON1) //Left key, the middle key is BUTTON2 return InputEvent.BUTTON1_MASK; if (button == MouseEvent.BUTTON3) //Right key return InputEvent.BUTTON3_MASK; return -100; }The whole program ends here. The above program does not implement encapsulation of robotic human threads. The complete code that can be used can be downloaded from the following site resources: http://xiazai.VeVB.COM/201608/yuanma/Java-RomoteControl(VeVB.COM).rar
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.