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程序设计有所帮助。