zoukankan      html  css  js  c++  java
  • java实现屏幕共享的小程序

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

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

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

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

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

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

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

       

        下面是不带鼠标的屏幕共享功能,比较简单,有待完善,不过可以作为一个工具类在后面集成使用。后面补充了把鼠标画上去的代码,只需要3行。

    首先是教师端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();    //垃圾回收
    			}
    		});
    	}
    }

    很晚了,从未成品中抽取了这么个小功能,因为答应某位童鞋给链接的,距离成品还有很多要写,后续补上吧。

    后续补充:

    把鼠标画到屏幕截图的方法,在SendScreenImg类中 BufferedImage img = robot.createScreenCapture(rect);后面,添加下面三行代码:

    BufferedImage cursor= ImageIO.read(new File("img/cursor.png"));  //把鼠标加载到缓存中
    Point p= MouseInfo.getPointerInfo().getLocation();               //获取鼠标坐标
    img.createGraphics().drawImage(cursor, p.x, p.y, null);          //在图片画上鼠标

    嗯,记得在工程下面建立一个img文件夹,在文件夹中放置名为cursor.png的鼠标图片,一定要png格式的,要求底色透明,可以去下载,也可以自己p图。

               给张运行时候的截图(按理说应该是有3个鼠标的,但是QQ截图也是没有的鼠标): LU~HY0$6I$J3TJ2(WHJV1$4

                本文出自博客园兰幽http://www.cnblogs.com/LZYY/

  • 相关阅读:
    angularJS指令--在各自的控制器里调用不同的函数
    npm install时的一个小问题
    按特定形式生成当前日期的函数
    js判断对象是否是数组的方法
    转正考试的几个考点
    JS 对象转化为数组
    requireJS随笔
    使用bootstrap-select插件,赋初始值
    理解Stream(一)——串行与终止操作
    python requests 库 首次使用
  • 原文地址:https://www.cnblogs.com/LZYY/p/4150282.html
Copyright © 2011-2022 走看看