Java實現(xiàn)遠程控制技術(shù)完整源代碼分享
Java實現(xiàn)遠程控制技術(shù)
java自帶的java.net.和java.awt.robot. 的混合可以用于實現(xiàn)通過網(wǎng)絡對另一臺計算機的遠程控制,其中包括控制遠程計算機鼠標的動作和鍵盤的輸入,以及實時獲得遠程計算機屏幕的圖像。本文將用簡潔的語言和由淺入深的邏輯,教大家如何掌握這個技術(shù)。
首先先看一下效果圖:
遠程端計算機界面:
控制端計算機界面:
控制端輸入:
遠程端輸入:

一下開始詳細介紹遠程控制的技術(shù)思路。
首先兩臺計算機通過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)來交換數(shù)據(jù)了
接下來大家可以想一想,要實現(xiàn)遠程控制的兩臺計算機需要交換什么信息呢?首先被控制端需要不斷向控制端提供截取的屏幕圖像(這個我們將會用java.awt.robot來實現(xiàn)),然后鼠標和鍵盤根據(jù)控制端傳來的事件(inputEvent)來做出相同的操作(用robot來實現(xiàn))。然后控制端當然首先要接收被控制端傳來的圖像并且反映到一個面板上(pane),然后監(jiān)聽本機上鍵盤鼠標的動作再傳給被控制端的主機(我們通過在面板pane上設置一個監(jiān)聽器listener來實現(xiàn))
這里遇到的一個問題就是用于傳送的圖片無論是用image還是用bufferedImage都是不可串行化的。所以不能用I/OStream進行傳送,所以為了解決這個問題,我們需要把圖像數(shù)據(jù)封裝在一個類里面并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; // 文件內(nèi)容
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;}
}
這樣就可以實現(xiàn)圖像通過ObjectInputStream和ObjectOutputStream的串行化傳播了
了解了以上基礎之后首先我們要完成控制端的UI界面設置,圖片接收,和鍵盤鼠標動作監(jiān)聽:
首先是設置接收圖片:
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的大小然后展示出來
下一步就是設置面板屬性和監(jiān)聽器:
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);
}
監(jiān)聽器:
public static void setListener( JFrame frame){
//panel設置監(jiān)聽器
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();
}
以上就完成了控制端。
接下來我們將構(gòu)建被控制端:
被控制端需要使用robot來截圖并發(fā)送,而且需要寫一個方法來對接收到的InputEvent進行反應
首先是截圖和發(fā)送:
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++) {
//截取指定大小的屏幕區(qū)域
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\目錄作為臨時文件的存放地方,讀者使用這個代碼的時候需要自己設置臨時文檔的存放
然后實現(xiàn)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;
}
整個程序到這里就可以結(jié)束了。上面的程序并沒有實現(xiàn)對機器人類線程的封裝。完整可以用的代碼可以在以下站內(nèi)資源處下載我的資源:http://xiazai.jb51.net/201608/yuanma/Java-RomoteControl(jb51.net).rar
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- Java UrlRewriter偽靜態(tài)技術(shù)運用深入分析
- 總結(jié)Java常用到的六個加密技術(shù)和代碼
- 識別率很高的java文字識別技術(shù)
- JAVA Web實時消息后臺服務器推送技術(shù)---GoEasy
- 分頁技術(shù)原理與實現(xiàn)之Java+Oracle代碼實現(xiàn)分頁(二)
- java的poi技術(shù)讀取和導入Excel實例
- Java中四種XML解析技術(shù)
- PHP、JAVA、.NET這三種技術(shù)的區(qū)別分析
- JAVA使用JDBC技術(shù)操作SqlServer數(shù)據(jù)庫實例代碼
- 你應該知道的21個Java核心技術(shù)
相關文章
SpringData如何通過@Query注解支持JPA語句和原生SQL語句
這篇文章主要介紹了SpringData如何通過@Query注解支持JPA語句和原生SQL語句,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
100-200之間所有素數(shù)求和程序代碼(二個版本)
寫一個求100-200之間素數(shù),并求和的程序,大家參考使用吧2013-11-11
淺談Java中向上造型向下造型和接口回調(diào)中的問題
這篇文章主要介紹了淺談Java中向上造型向下造型和接口回調(diào)中的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08

