Socket网络编程练习-----远程协助工具

来源:互联网 发布:农村淘宝怎么卖农产品 编辑:程序博客网 时间:2024/04/30 01:08

  网络编程是指通过使用套接字来达到进程间相互通信的目的,狭义上的网络编程就是指在两台或两台以上的计算机之间传输数据。我们程序员发送到指定的位置,或者接收到指定的数据。在发送和接收数据时,大部分的计算机语言都设计了专门的API实现这些功能,而我们只需要调用即可。
  在Java中,支持TCP网络编程的包是java.net包,以java.net包下面的Socket类代表客户端连接,ServerSocket类代表服务器连接。
  在这里我们要实现远程控制还需要使用java.awt.robot类。通过网络实现对另一台计算机的远程控制,其实就是控制远程计算机的鼠标和键盘动作,还有一个就是要获取远程计算机屏幕的图像。
  首先先讲一下思路:要实现远程控制一般有三个部分,分别是控制端、被控制端,还有一个服务端。这里为了简单,省略了服务端,将服务端和被控制端合到了一起。以下统称为大家熟悉的客户端和服务端。
  客户端主要实现:
    1、接受服务端发送过来的图片
    2、监听事件,发送键盘事件和鼠标事件
  服务端主要实现:
    1、将电脑桌面发送到客户端
     2、监听事件,发送键盘事件和鼠标事件
     3、使用Robot类进行鼠标和键盘的自动化操作

具体实现

首先,两台计算机需要通过java.net.Socket进行连接。
服务端应该有一个ServerSocket,并且初始化输出流:

public static void main(String[] args) throws Exception {        //实例化服务端监听 在 1234端口        ServerSocket sever = new ServerSocket(1234);        System.out.println("服务器已经启动...");        Socket socket = sever.accept(); //等待接受请求        System.out.println("有客户已经连接");        DataOutputStream dataOut =         new DataOutputStream(socket.getOutputStream());    }
客户端应该有一个Socket去连接服务端,并且初始化输入输出流:
public static void main(String[] args)         throws Exception, IOException{        Socket socket = new Socket("127.0.0.1",1234);        DataInputStream dataIn = new DataInputStream(socket.getInputStream());        ObjectOutputStream objectOut = new ObjectOutputStream(socket.getOutputStream());    }   

  现在两台计算机已经连通了,接下来就需要具体实现数据的交换。由于我们的被控制端和服务端是和在一起的,按照我上面写的,现在服务端需要将电脑桌面发送给客服端,怎么讲桌面发到客户端呢?这里我们使用java.awt.Robot实现。

Robot robot = new Robot();//截取整个屏幕//使用Toolkit工具包获取当前操作系统的一些信息Dimension dm = Toolkit.getDefaultToolkit().getScreenSize();Rectangle rect = new Rectangle(dm);

这里截出来的图片我们一定要用byte数组经常传送,我们为图片的传输和处理创建一个线程:

/*创建一个子线程,用来将本地图片发送到客户端去*/class ImageThread extends Thread{    private DataOutputStream dataOut;    public ImageThread (DataOutputStream dataOut){        this.dataOut = dataOut;    }    @Override    public void run() {        try {            Robot robot = new Robot();            //截取整个屏幕            //使用Toolkit工具包获取当前操作系统的一些信息            Dimension dm = Toolkit.getDefaultToolkit().getScreenSize();            Rectangle rect = new Rectangle(dm);            BufferedImage img ;            byte[] imageByte;            while(true){                img = robot.createScreenCapture(rect);                //压缩处理以及转换成byte数组                imageByte = getByteImage(img);                //将图片的长度告诉客户端  客户端必须要用byte数组接受                dataOut.writeInt(imageByte.length);                //将图片传输到客户端                dataOut.write(imageByte);                Thread.sleep(50);            }        } catch (Exception e) {            e.printStackTrace();        }    }    private byte[] getByteImage(BufferedImage image) throws ImageFormatException, IOException{        ByteArrayOutputStream bout = new ByteArrayOutputStream();        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bout);        encoder.encode(image);        return bout.toByteArray();    }}

接下来就是客户端接收并处理图片,这里我们将接收到的图片在一个面板上显示。

//定义一个窗体class  ClientWindow extends JFrame{    private JLabel backGround;    private ObjectOutputStream objectOut;    public void repaintImage(byte[] image){        backGround.setIcon( new ImageIcon(image));        this.repaint();    }    public ClientWindow(ObjectOutputStream objectOut){        this.objectOut = objectOut;        this.setTitle("远程协助工具");        this.setSize(1024, 768);        backGround = new JLabel();        JPanel jp = new JPanel();        jp.add(backGround);        JScrollPane scrollPanel = new JScrollPane(jp);        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        this.add(scrollPanel);        this.setVisible(true);    }}

  到这里我们已经可以从控制端看到被控制端的电脑桌面,接下来就是要监听键盘鼠标事件了。
  先是客户端的键盘鼠标事件监听 
  

//绑定键盘事件 
   addKeyListener(new KeyListener(){
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyPressed(KeyEvent e) {
sendEvent(e);
}
@Override
public void keyReleased(KeyEvent e) {
sendEvent(e);
}
});
//绑定鼠标事件
backGround.addMouseListener(new MouseListener(){
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {
sendEvent(e);
}
@Override
public void mouseReleased(MouseEvent e) {
sendEvent(e);
}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
});
//绑定鼠标移动事件
backGround.addMouseMotionListener(new MouseMotionListener(){
@Override
public void mouseDragged(MouseEvent e) {
sendEvent(e);
}
@Override
public void mouseMoved(MouseEvent e) {
sendEvent(e);
}
});

将事件传送到服务端:

public void sendEvent(InputEvent event){        try {            objectOut.writeObject(event);        } catch (Exception e) {            e.printStackTrace();        }    }

  然后是服务端的键盘鼠标事件监听和处理,我们创建一个线程来处理
  

/** 
* 处理接受到的键盘鼠标事件
* @author weixian
*/
class EventThread extends Thread{
private ObjectInput objectIn;
private Robot robot;
public EventThread(ObjectInputStream objectIn){
this.objectIn = objectIn;
}
@Override
public void run() {
try {
robot = new Robot();
while(true){
Object event = objectIn.readObject();
InputEvent inEvent = (InputEvent)event;
//处理事件
actionEvent(inEvent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void actionEvent(InputEvent 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{
MouseEvent e = (MouseEvent)event;
int type = e.getID();
if(type == Event.MOUSE_DOWN){
robot.mousePress(getMouseButton(e.getButton()));
}else if(type == Event.MOUSE_UP){
robot.mouseRelease(getMouseButton(e.getButton()));
}else if(type == Event.MOUSE_MOVE){
robot.mouseMove(e.getX(), e.getY());
}else if(type == Event.MOUSE_DRAG){
robot.mouseMove(e.getX(), e.getY());
}
}
}
private int getMouseButton(int button){
if(button == MouseEvent.BUTTON1){
return InputEvent.BUTTON1_MASK;
}else if(button == MouseEvent.BUTTON2){
return InputEvent.BUTTON2_MASK;
}if(button == MouseEvent.BUTTON3){
return InputEvent.BUTTON3_MASK;
}else{
return -1;
}
}
}

到这里我们就可以基本实现远程控制了。
源代码下载:https://github.com/zhanlong-dw/removte

3 0