java實(shí)現(xiàn)遠(yuǎn)程桌面的實(shí)例代碼
java實(shí)現(xiàn)遠(yuǎn)程桌面的實(shí)例代碼
控制端將鼠標(biāo)事件傳遞到服務(wù)端
服務(wù)端拿到鼠標(biāo)事件之后傳輸?shù)娇蛻舳?/strong>
客戶端拿到鼠標(biāo)事件之后,通過robot類即可完成,并且截屏將圖片發(fā)給服務(wù)器,服務(wù)器再發(fā)給控制端

被我簡化之后得到

//先介紹一下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);//鼠標(biāo)移動(dòng)
r.mousePress(InputEvent.BUTTON1_MASK ); //鼠標(biāo)按下
r.mouseRelease(InputEvent.BUTTON1_MASK);//鼠標(biāo)松開
r.keyPress((int)'A'); //鍵盤按下 (int)'A'表示將A轉(zhuǎn)換成鍵盤對(duì)應(yīng)的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);
//四個(gè)參數(shù)x y width height
jframe.setVisible(true);
jframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE );
//構(gòu)建一個(gè)死循環(huán)動(dòng)態(tài)截取
while(true){
BufferedImage image = robot.createScreenCapture(new Rectangle(0,0,1366,768));//截取屏幕
label.setIcon(new ImageIcon(image));
Thread.sleep(50);
}
}
}
//遠(yuǎn)程控制原理講解
//分為server端和client端,
//原本server端只作為轉(zhuǎn)發(fā),作為演示,就不寫轉(zhuǎn)發(fā)
//也就是client端控制server端E
/**
* 這里我采用的是,在client端也就是操控端,接收到server端發(fā)送過來的screen之后,然后發(fā)送鼠標(biāo)事件過去
* 然后再用robot處理
* 傳輸方式用socket+io即可處理
* 屏幕截取和圖片壓縮采用了robot的屏幕截取功能和jdk自帶的圖片編碼器,將其轉(zhuǎn)換成一個(gè)字節(jié)數(shù)組
* 發(fā)送給server端之后,robot通過io+socket可以直接拿到object對(duì)象,強(qiáng)制轉(zhuǎn)換成InputEvent(keyEvent和MouseEvent都繼承)之后
* 通過判斷event類型,分別處理即可,這里在服務(wù)端需要用到兩個(gè)線程,一個(gè)是屏幕截取和發(fā)送給客戶端,一個(gè)是用來監(jiān)聽客戶端
* 傳遞過來的事件
*/
//下面是具體實(shí)現(xiàn)代碼
//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;
/**
* 服務(wù)端
* @author 啞元
*
*/
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(80);
System.out.println("服務(wù)器已經(jīng)正常啟動(dòng)");
Socket socket = server.accept();//等待接收請(qǐng)求,阻塞方法
System.out.println("有客戶端連接");
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
//將客戶端與服務(wù)器端鏈接的輸出流交個(gè)ImageThread處理
ImageThread imageThread = new ImageThread(dos);
new Thread(imageThread).start();
new Thread(new EventThread(new ObjectInputStream(socket.getInputStream()))).start();
}
}
/**
* 用來處理接收過來的鼠標(biāo)事件或者鍵盤事件
*/
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();//得知由客戶端傳遞過來的是一個(gè)object對(duì)象
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類執(zhí)行
* @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());//鼠標(biāo)拖動(dòng)
}
}
}
/**
* 返回鼠標(biāo)的真正事件,鼠標(biāo)時(shí)間不能直接處理,需要進(jìn)過轉(zhuǎn)換
* @return
*/
public int getMouseKey(int button){
if(button == MouseEvent.BUTTON1){//鼠標(biāo)左鍵
return InputEvent.BUTTON1_MASK;
}else if(button == MouseEvent.BUTTON2){//鼠標(biāo)右鍵
return InputEvent.BUTTON2_MASK;
}else if(button == MouseEvent.BUTTON3){//滾輪
return InputEvent.BUTTON3_MASK;
}else{
return 0;
}
}
}
//屏幕截取器和發(fā)送器,這里需要拿到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.*;
/**
* 用來將圖片數(shù)據(jù)發(fā)送
* @author 啞元
*
*/
public class ImageThread implements Runnable{
DataOutputStream dos = null; //數(shù)據(jù)輸出流
public ImageThread(DataOutputStream dos){
this.dos = dos;
}
@Override
public void run() {
try {
Robot robot = new Robot();
//截取整個(gè)屏幕
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數(shù)組
* @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);
//轉(zhuǎn)換成byte數(shù)組
return baos.toByteArray();
}
}
--------------------------------------------------------------------------------------
//client端,用來接收creen圖片和發(fā)送鼠標(biāo)事件
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()]; //先拿到傳過來的數(shù)組長度
dis.readFully(imageBytes); //所有的數(shù)據(jù)存放到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("遠(yuǎn)程控制程序");
label = new JLabel();
JPanel p = new JPanel();
p.add(label);
JScrollPane scroll = new JScrollPane(p);//給p面板添加滾動(dòng)條
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實(shí)現(xiàn)遠(yuǎn)程桌面的實(shí)例代碼就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- java通過Idea遠(yuǎn)程一鍵部署springboot到Docker詳解
- Java關(guān)于遠(yuǎn)程調(diào)試程序教程(以Eclipse為例)
- Java遠(yuǎn)程連接Linux服務(wù)器并執(zhí)行命令及上傳文件功能
- java利用SMB讀取遠(yuǎn)程文件的方法
- Java VisualVM監(jiān)控遠(yuǎn)程JVM(詳解)
- java遠(yuǎn)程連接調(diào)用Rabbitmq的實(shí)例代碼
- Java利用Sping框架編寫RPC遠(yuǎn)程過程調(diào)用服務(wù)的教程
- java進(jìn)行遠(yuǎn)程部署與調(diào)試及原理詳解
相關(guān)文章
經(jīng)典再現(xiàn) 基于JAVA平臺(tái)開發(fā)坦克大戰(zhàn)游戲
經(jīng)典再現(xiàn),這篇文章主要介紹了基于JAVA平臺(tái)開發(fā)坦克大戰(zhàn)游戲的相關(guān)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06
最新IDEA?2022基于JVM極致優(yōu)化?IDEA啟動(dòng)速度的方法
這篇文章主要介紹了IDEA?2022最新版?基于?JVM極致優(yōu)化?IDEA?啟動(dòng)速度,需要的朋友可以參考下2022-08-08
如何解決idea安裝插件后報(bào)錯(cuò)打不開問題
這篇文章主要介紹了如何解決idea安裝插件后報(bào)錯(cuò)打不開問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
IntelliJ IDEA2021.1 配置大全(超詳細(xì)教程)
這篇文章主要介紹了IntelliJ IDEA2021.1 配置大全(超詳細(xì)教程),需要的朋友可以參考下2021-04-04
使用JAVA實(shí)現(xiàn)郵件發(fā)送功能的圖文教程
郵件發(fā)送其實(shí)是一個(gè)非常常見的需求,用戶注冊(cè),找回密碼等地方,都會(huì)用到,下面這篇文章主要給大家介紹了關(guān)于使用JAVA實(shí)現(xiàn)郵件發(fā)送功能的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06

