Java实现远程控制技术完整源代码分享
作者:Charchunchiu 发布时间:2022-04-10 20:31:53
Java实现远程控制技术
java自带的java.net.和java.awt.robot. 的混合可以用于实现通过网络对另一台计算机的远程控制,其中包括控制远程计算机鼠标的动作和键盘的输入,以及实时获得远程计算机屏幕的图像。本文将用简洁的语言和由浅入深的逻辑,教大家如何掌握这个技术。
首先先看一下效果图:
远程端计算机界面:
控制端计算机界面:
控制端输入:
远程端输入:
一下开始详细介绍远程控制的技术思路。
首先两台计算机通过java.net的Socket来进行连接。
一端先打开一个ServerSocket,然后另外一端用socket进行连接。
服务器端
应该设置一个ServerSocket,并且初始化需要用到的输入输出流:
public static void OpenServer() throws IOException, ClassNotFoundException{
System.out.println("ServerStart.....");
ServerSocket server = new ServerSocket(7777);
socket = server.accept();
System.out.println("连接上...\n"+socket);
OIS = new ObjectInputStream(socket.getInputStream());
OOS=new ObjectOutputStream(socket.getOutputStream());
}
客户机端
应该用socket去连接服务器,并且初始化输入输出流:
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());
}
这样两台计算机就链接在一起并且可以通过流(InputStream和OutputStream)来交换数据了
接下来大家可以想一想,要实现远程控制的两台计算机需要交换什么信息呢?首先被控制端需要不断向控制端提供截取的屏幕图像(这个我们将会用java.awt.robot来实现),然后鼠标和键盘根据控制端传来的事件(inputEvent)来做出相同的操作(用robot来实现)。然后控制端当然首先要接收被控制端传来的图像并且反映到一个面板上(pane),然后监听本机上键盘鼠标的动作再传给被控制端的主机(我们通过在面板pane上设置一个 * listener来实现)
这里遇到的一个问题就是用于传送的图片无论是用image还是用bufferedImage都是不可串行化的。所以不能用I/OStream进行传送,所以为了解决这个问题,我们需要把图像数据封装在一个类里面并implements Serializable接口
图像类如下:
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; // 文件名称
private long fileLength; // 文件长度
private byte[] fileContent; // 文件内容
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;}
}
这样就可以实现图像通过ObjectInputStream和ObjectOutputStream的串行化传播了
了解了以上基础之后首先我们要完成控制端的UI界面设置,图片接收,和键盘鼠标动作监听:
首先是设置接收图片:
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);
imag_lab.setIcon(new ImageIcon(bi));
imag_lab.repaint();//销掉以前画的背景
}
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;
}
这样接收了来自ObjectInputStream的Message类之后就可以把图片重新设置到面板pane的大小然后展示出来
下一步就是设置面板属性和 * :
public static void showUI(){
//控制台标题
JFrame jf = new JFrame("控制台");setListener(jf);
//控制台大小
jf.setSize(500, 400);
//imag_lab用于存放画面
imag_lab = new JLabel();
jf.add(imag_lab);
//设置控制台可见
jf.setVisible(true);
//控制台置顶
jf.setAlwaysOnTop(true);
jf.setResizable(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
* :
public static void setListener( JFrame frame){
//panel设置 *
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();
}
以上就完成了控制端。
接下来我们将构建被控制端:
被控制端需要使用robot来截图并发送,而且需要写一个方法来对接收到的InputEvent进行反应
首先是截图和发送:
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++) {
//截取指定大小的屏幕区域
Rectangle rec = new Rectangle(0, 0, (int) dm.getWidth(), (int) dm
.getHeight());
BufferedImage bimage = robot.createScreenCapture(rec);
//将图片保存到文件中
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();
}
}
注意到这段代码中使用了D:\OUT\目录作为临时文件的存放地方,读者使用这个代码的时候需要自己设置临时文档的存放
然后实现robot对于接收到的InputEvent指令进行操作:
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 ; //鼠标事件
MouseWheelEvent mwevent = null ;//鼠标滚动事件
KeyEvent kevent = null ; //键盘事件
int mousebuttonmask = -100; //鼠标按键
switch (event.getID()){
case MouseEvent.MOUSE_MOVED : //鼠标移动
mevent = ( MouseEvent )event ;
action.mouseMove( mevent.getX() , mevent.getY() );
break ;
case MouseEvent.MOUSE_PRESSED : //鼠标键按下
mevent = ( MouseEvent ) event;
action.mouseMove( mevent.getX() , mevent.getY() );
mousebuttonmask = getMouseClick(mevent.getButton() );
if(mousebuttonmask != -100)
action.mousePress(mousebuttonmask);
break;
case MouseEvent.MOUSE_RELEASED : //鼠标键松开
mevent = ( MouseEvent ) event;
action.mouseMove( mevent.getX() , mevent.getY() );
mousebuttonmask = getMouseClick( mevent.getButton() );//取得鼠标按键
if(mousebuttonmask != -100)
action.mouseRelease( mousebuttonmask );
break ;
case MouseEvent.MOUSE_WHEEL : //鼠标滚动
mwevent = ( MouseWheelEvent ) event ;
action.mouseWheel(mwevent.getWheelRotation());
break ;
case MouseEvent.MOUSE_DRAGGED : //鼠标拖拽
mevent = ( MouseEvent ) event ;
action.mouseMove( mevent.getX(), mevent.getY() );
break ;
case KeyEvent.KEY_PRESSED : //按键
kevent = ( KeyEvent ) event;
action.keyPress( kevent.getKeyCode() );
break ;
case KeyEvent.KEY_RELEASED : //松键
kevent= ( KeyEvent ) event ;
action.keyRelease( kevent.getKeyCode() );
break ;
default: break ;
}
}
private static int getMouseClick(int button) { //取得鼠标按键
if (button == MouseEvent.BUTTON1) //左键 ,中间键为BUTTON2
return InputEvent.BUTTON1_MASK;
if (button == MouseEvent.BUTTON3) //右键
return InputEvent.BUTTON3_MASK;
return -100;
}
整个程序到这里就可以结束了。上面的程序并没有实现对机器人类线程的封装。完整可以用的代码可以在以下站内资源处下载我的资源:http://xiazai.jb51.net/201608/yuanma/Java-RomoteControl(jb51.net).rar
猜你喜欢
- 概述:App几乎都离不开与服务器的交互,本文主要讲解了flutter网络请求三种方式 flutter自带的HttpClient、 第三方库h
- 介绍跨域CORS,全称是"跨域资源共享"(Cross-origin resource sharing)当页面发出跨域请求
- 一、流程和任务的关系以下是一个简单的请假流程图,其中有一个开始事件,两个用户任务,一个结束事件。启动流程后,activiti会自动创建第一个
- 本项目是前端vue3,后端springboot开发 需求为:前端导入表格,后端处理表格存储数据,点击按钮可以导出表格。上传效果:前端点击上传
- 这篇文章主要介绍了Java中遍历ConcurrentHashMap的四种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一
- 整型变量基本语法格式int变量名= 初始值;代码示例int a = 10;int表示变量的类型是一个整型。在 Java 中, 一个int变量
- 最近在研究dubbo时,发现了JAVA的SPI特性。SPI的全名为Service Provider Interface,是JDK内置的一种服
- (由于篇幅原因阐述的不够详细科学,不喜勿喷)。经常看到java中对byte数组的不同定义,粗略整理的一下:一个字节(byte)=8位(bit
- 大体思路如果发总金额为 m的 n 个红包,先用一个长度为 n的临时数组 a 存放 n个随机双精度小数 ,然后用 sum表示数组
- 本文为大家分享了使用栈的迷宫算法java版,主要考察栈的使用,供大家参考,具体内容如下主要思路如下: do { if(当前位置可通过) {
- 自定义starterSpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进 starter,应用
- Web UI项目中, 很多 Spring controller 视图函数直接返回 html 页面, 还有一些视图函数是要重定向或转发到其他的
- 前言:在 Java 语言中,并发编程都是依靠线程池完成的,而线程池的创建方式又有很多,但从大的分类来说,线程池的创建总共分为两大类:手动方式
- 用一个7 x 7的矩形表示迷宫,0和1分别表示的是通路和障碍。通过设计编写程序找到蓝色小球达到蓝色旗子的路线思路:构建一个迷宫(用二维数组)
- 改了个bug,发现这个东西以前不知道,搜索了一下,看到的都是长篇大论,还谈js的源码,也是醉了。我就简单的说说这个是干啥的。简单说:就是触发
- 本文实例为大家分享了java生成字母验证码的具体代码,供大家参考,具体内容如下import java.awt.BasicStroke;imp
- 本文实例为大家分享了iOS新浪微博分享功能的具体代码,供大家参考,具体内容如下做新浪分享 需先去http://open.weibo.com/
- 其实这个表示有点不太对,应该是 Druid 动态切换数据源的方法,只是应用在了 springboot 框架中,准备代码准备了半天,之前在一次
- 在第一次启动项目的时候,由于使用了RabbitMQ的默认guest账号,怎么也登不进去,后来还是在Admin重新创建了一个其他的账号,然后开
- 最近在做项目的时候有用到对两个集合中的元素进行对比求其交集的情况,因为涉及到的数据量比较大,所以在进行求两个集合中元素交集的时候,就应该考虑