用 java 怎么实现 QQ 中远程协助功能哪?
一、
JDK中的Robot类用于产生与本地操作系统有关的底层输入、测试应用程序运行或自动控制应用程序运行。
Robot类提供了一个方法:createScreenCapture(。。。),可以直接将全屏幕或某个屏幕区域的像素拷贝到一个BufferedImage
对象中。
实现原理其实很简单:
在被监视者的机器上,运行一个线程,每隔一段时间就自动截图,并把截图压缩发送到指定的机器上;
然后响应监控端发来的事件。这样就实现了对受监控端的控制。
在监视机器上,也是运行一个线程,接收发送过来的图片包,解压,并绘制到当前的窗口上,
然后再添加对鼠标、键盘的监听事件。
这样就基本完成了。
在局域网中,感觉运行的效果还不错,控制事件能够准确响应。
改进想法:
1、用UDP代替TCP来实现此功能,
2、使用反向连接即受监控端主动连接监控端而不是监控端连接受监控端。
二、
贴出部分代码(代码太多啦)
受监控端:
package remotemonitor.server;
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class CaptureSendImage extends Thread{
private static long GETIMAGE_TIME = 10; // 图片采集时间
private Rectangle rect;
/**
* 此类用于为测试自动化、自运行演示程序和其他需要控制鼠标和键盘的应用程序生成本机系统输入事件。
* Robot 的主要目的是便于 Java 平台实现自动测试。
*/
private Robot robot;
private Socket socket;
public CaptureSendImage(Socket socket){
try {
this.socket = socket;
robot = new Robot();
//以全屏区域构造一个新的 Rectangle,其左上角为 (0,0),其宽度和高度由 Dimension 参数指定
rect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
} catch (AWTException e) {
e.printStackTrace();
}
}
public void run(){
try {
JPEGImageEncoder encoder =JPEGCodec.createJPEGEncoder(socket.getOutputStream());
BufferedImage image = null;
while(true){
image = robot.createScreenCapture(rect);
encoder.encode(image);
Thread.sleep(GETIMAGE_TIME);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
try {
if(socket!=null)
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
监控端:
package remotemonitor.client;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.Socket;
import javax.swing.JOptionPane;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageDecoder;
public class ReciveImage extends Thread {
private DrawImage drawImage;
private Socket socket;
public ReciveImage(Socket socket, DrawImage drawImage) {
this.socket = socket;
this.drawImage = drawImage;
}
public void run() {
try {
JPEGImageDecoder de = JPEGCodec.createJPEGDecoder(socket.getInputStream());// 获得图像解码器
BufferedImage image = null;
while (true) {
image = de.decodeAsBufferedImage();// 从流中解码图像
if (image != null) {
drawImage.saveImage(image);// 重画图像
}else{
JOptionPane.showMessageDialog(null,"受控端关闭或者网络异常","提示消息",JOptionPane.WARNING_MESSAGE);
}
}
} catch (Exception e) {
//e.printStackTrace();
JOptionPane.showMessageDialog(null,"受控端关闭或者网络异常","提示消息",JOptionPane.WARNING_MESSAGE);
}
}
public boolean isClose(){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
return false;
}
return true;
}
}
效果图: