java实现屏幕共享功能实例分析

本文实例讲述了java实现屏幕共享功能的方法。分享给大家供大家参考。具体分析如下:

最近在做软件软件工程的课程设计,做一个用于实验室的屏幕监控系统,参考各种前人代码,最后领悟之后要转换自己的代码,初学者都是这样模仿过来的。

说到屏幕监控系统,有教师端和学生端,教师端就是Server端,学生端就做Client端。系统里比较有趣的一个地方应该算是屏幕广播与屏幕监控吧,其余什么点名签到,锁屏,定时关机的,就相对来说简单点。

屏幕广播,在功能实现上面,说白了,就是教师端的机器不断截取屏幕信息,以图片的形式发送到每一个学生端的电脑上面,由此学生能够看见老师在电脑上的操作,这就是所谓的屏幕广播。

这里面有个麻烦的地方,就是截取屏幕图片的时候,是没有鼠标信息。不过有两种解决办法:

①在发送截图信息时,在图片上绘制一个鼠标,这样在学生端就会有两个鼠标,学生端可以移动自己电脑上的鼠标。

②发送教师端的鼠标坐标到学生端上,学生端的电脑鼠标根据坐标信息实时移动,这里其实是涉及到控制的功能了,学生端就不能移动鼠标了。

屏幕监控相对棘手点,其实这是这包含俩功能:
①教师监控所有学生电脑屏幕的功能;
②教师控制某一个学生的电脑;
因为涉及到并发,每个client都要实时的把屏幕信息发到教师端上,会有点麻烦,不过还是可以实现。

这里暂时实现了不带鼠标的屏幕共享功能,比较简单,有待完善,不过可以作为一个工具类在后面集成使用。

首先是教师端Server:

package Test;

 

import java.awt.Dimension;

import java.awt.Rectangle;

import java.awt.Robot;

import java.awt.Toolkit;

import java.awt.image.BufferedImage;

import java.io.DataOutputStream;

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.zip.ZipEntry;

import java.util.zip.ZipOutputStream;

 

import javax.imageio.ImageIO;

 

/*

 * ly  2014-11-20

 * 该类实时发送截屏消失,多线程实现,不包含鼠标信息,且没有做对每个Client做优化处理

 */

public  class SendScreenImg extends Thread

{

    public static int SERVERPORT=8000;

    private ServerSocket serverSocket;

    private Robot robot;

    public  Dimension screen;

    public Rectangle rect ;

    private Socket socket; 

     

    public static void main(String args[])

    {

        new SendScreenImg(SERVERPORT).start();

    }

     

    //构造方法  开启套接字连接      机器人robot   获取屏幕大小

    public SendScreenImg(int SERVERPORT)

    {

        try {

            serverSocket = new ServerSocket(SERVERPORT);

            serverSocket.setSoTimeout(864000000);

            robot = new Robot();

        } catch (Exception e) {

            e.printStackTrace();

        }

        screen = Toolkit.getDefaultToolkit().getScreenSize();  //获取主屏幕的大小

        rect = new Rectangle(screen);                          //构造屏幕大小的矩形

    }

     

    @Override

    public void run() 

    {

        //实时等待接收截屏消息

        while(true)

        {

            try{

                socket = serverSocket.accept();

                System.out.println("学生端口已经连接");

                ZipOutputStream zip = new ZipOutputStream(new DataOutputStream(socket.getOutputStream()));

                zip.setLevel(9);     //设置压缩级别

                 

                BufferedImage img = robot.createScreenCapture(rect);

                zip.putNextEntry(new ZipEntry("test.jpg"));

                ImageIO.write(img, "jpg", zip);

                if(zip!=null)zip.close();

                System.out.println("Client正在实时连接");

                

            } catch (IOException ioe) {

                System.out.println("连接断开");

            } finally {

                if (socket != null) {

                    try {

                        socket.close();

                    } catch (IOException e) {e.printStackTrace();}

                }

            }

        }

    }

}

然后是学生端Client:

package Test;

import java.awt.Frame;

import java.awt.Image;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

import java.io.DataInputStream;

import java.io.IOException;

import java.net.Socket;

import java.util.concurrent.TimeUnit;

import java.util.zip.ZipInputStream;

import javax.imageio.ImageIO;

import javax.swing.ImageIcon;

import javax.swing.JFrame;

import javax.swing.JLabel;

/*

 * ly  2014-11-20

 * 该类用于接收教师端的屏幕信息,不包括鼠标,待优化

 */

public  class ReceiveImages extends  Thread{

    public BorderInit frame ;

    public Socket socket;

    public String IP;

     

    public static void main(String[] args){

        new ReceiveImages(new BorderInit(), "127.0.0.1").start();

    }

    public ReceiveImages(BorderInit frame,String IP)

    {

        this.frame = frame;

        this.IP=IP;

    }

     

    public void run() {

        while(frame.getFlag()){

            try {

                socket = new Socket(IP,8000);

                DataInputStream ImgInput = new DataInputStream(socket.getInputStream());

                ZipInputStream imgZip = new ZipInputStream(ImgInput);

                 

                imgZip.getNextEntry();             //到Zip文件流的开始处

                Image img = ImageIO.read(imgZip);  //按照字节读取Zip图片流里面的图片

                frame.jlbImg.setIcon(new ImageIcon(img));

                System.out.println("连接第"+(System.currentTimeMillis()/1000)%24%60+"秒");

                frame.validate();

                TimeUnit.MILLISECONDS.sleep(50);// 接收图片间隔时间

                imgZip.close();

                 

            } catch (IOException | InterruptedException e) {

                System.out.println("连接断开");

            }finally{

                try {

                    socket.close();

                } catch (IOException e) {}  

            }       

        }   

    }

}

 

//Client端窗口辅助类,专门用来显示从教师端收到的屏幕信息

class BorderInit extends JFrame

{

    private static final long serialVersionUID = 1L;

    public JLabel jlbImg;

    private boolean flag;

    public boolean getFlag(){

        return this.flag;

    }

    public BorderInit()

    {

        this.flag=true;

        this.jlbImg = new JLabel();

        this.setTitle("远程监控--IP:"  + "--主题:" );

        this.setSize(400, 400);

        //this.setUndecorated(true);  //全屏显示,测试时最好注释掉

        //this.setAlwaysOnTop(true);  //显示窗口始终在最前面

        this.add(jlbImg);

        this.setLocationRelativeTo(null);

        this.setExtendedState(Frame.MAXIMIZED_BOTH);

        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

        this.setVisible(true);

        this.validate();

     

        //窗口关闭事件

        this.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent e) {

                flag=false;

                BorderInit.this.dispose();

                System.out.println("窗体关闭");

                System.gc();    //垃圾回收

            }

        });

    }

}

这里就从未成品中抽取了这么个小功能,距离成品还有很多要写,感兴趣的朋友可以在此基础上加以完善。

希望本文所述对大家的Java程序设计有所帮助。