说到屏幕监控系统,有教师断和学生端,教师端就是Server端,学生端就做Client端。系统里比较有趣的一个地方应该算是屏幕广播与屏幕监控吧,其余什么点名签到,锁屏,定时关机的,就相对来说简单点。
屏幕广播,在功能实现上面,说白了,就是教师端的机器不断截取屏幕信息,以图片的形式发送到每一个学生端的电脑上面,由此学生能够看见老师在电脑上的操作,这就是所谓的屏幕广播。
这里面有个麻烦的地方,就是截取屏幕图片的时候,是没有鼠标信息。不过有两种解决办法:
①在发送截图信息时,在图片上绘制一个鼠标,这样在学生端就会有两个鼠标,学生端可以移动自己电脑上的鼠标。
②发送教师端的鼠标坐标到学生端上,学生端的电脑鼠标根据坐标信息实时移动,这里其实是涉及到控制的功能了,学生端就不能移动鼠标了。
屏幕监控相对棘手点,其实这是这包含俩功能:①教师监控所有学生电脑屏幕的功能;②教师控制某一个学生的电脑; 因为涉及到并发,每个client都要实时的把屏幕信息发到教师端上,会有点麻烦,不过还是可以实现。
下面是不带鼠标的屏幕共享功能,比较简单,有待完善,不过可以作为一个工具类在后面集成使用。后面补充了把鼠标画上去的代码,只需要3行。
首先是教师端Server:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
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);后面,添加下面三行代码:
1
2
3BufferedImage 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截图也是没有的鼠标):
深蓝互联成立于2013年,是一家物联网硬件开发及软件应用服务商,获得多次获得国家高新技术企业资质的企业。深蓝互联专注软硬件技术开发的专业性技术公司。我们从事软硬件开发十年,擅长SaaS 平台开发、APP小程序开发、软硬件结合开发,在视觉识别处理、数据架构、云计算、多线程高并发和集群、数据安全加密和防护方便有很深的技术积累。
我们拥有专业优秀的设计和技术团队,以极具创意的 UI 设计、精湛卓越的开发技术,专业的网络策划团队。公司多年来投入打造物联网SaaS平台,集成了公司研发的多款智能物联网终端(智能鲜米机、生鲜售货机、自助洗车机、小区电瓶车充电系统等)。
公司一直坚持以研发为导向,打造软硬件结合的物联网平台系统。将一直坚持提高开发的技术实力更好的为我们的客户服务!
文章来自深蓝互联http://www.szdbi.com/webxt/385.html转载请注明出处!