• 屏幕广播


    1、服务器端

      1 public class ThreadMain {
      2 
      3     public static void main(String[] args) {
      4         new ServerSender().start();
      5     }
      6 
      7 }
      8 
      9 
     10 public class ServerSender {
     11     //UDP套接字
     12     private DatagramSocket socket;
     13     //创建机器人,抓图
     14     private Robot robot;
     15     private Rectangle rect;
     16     public ServerSender()  {
     17         try {
     18             socket=new DatagramSocket(8888);
     19             robot=new Robot();
     20             rect=new Rectangle(0, 0, 1366, 768);
     21         } catch (Exception e) {
     22             e.printStackTrace();
     23         }
     24     }
     25     public void start(){
     26         int i=0;
     27         while(true){
     28             sendOneScreen();
     29         }
     30     }
     31     private void sendOneScreen() {
     32         //1.抓取一屏幕
     33         byte[] frameData=catchOneScreen(true);
     34         //2.切割
     35         List<FrameUnit> units=splitScreen(frameData);
     36         //3.组装内容,并发送所有帧单元
     37         sendAllUnits(units);
     38     }
     39     //发送所有帧单元
     40     private void sendAllUnits(List<FrameUnit> units){
     41         for (FrameUnit unit:units) {
     42             //处理帧单元
     43             DatagramPacket pack=processUnit(unit);
     44             try {
     45                 socket.send(pack);
     46             } catch (IOException e) {
     47                 e.printStackTrace();
     48             }
     49         }
     50     }
     51     //处理帧单元
     52     private DatagramPacket processUnit(FrameUnit unit){
     53         byte[] buf=new byte[unit.getLength()+14];
     54         //时间戳
     55         byte[] timeBytes=bytesUtil.long2ByteArr(unit.getTimestamp());
     56         System.arraycopy(timeBytes, 0, buf, 0, 8);
     57         //count
     58         buf[8]=(byte) unit.getCount();
     59         //index
     60         buf[9]=(byte) unit.getIndex();
     61         //data长度
     62         byte[] unitLengBytes=bytesUtil.int2ByteArr(unit.getLength());
     63         System.arraycopy(unitLengBytes, 0, buf, 10, 4);
     64         //数据
     65         byte[] unitDataBytes=unit.getUnitData();
     66         System.arraycopy(unitDataBytes, 0, buf, 14, unitDataBytes.length);
     67         //设置数据报包的广播地址
     68         DatagramPacket pack=new DatagramPacket(buf, buf.length);
     69         InetSocketAddress addr=new InetSocketAddress("localhost", 9999);
     70         pack.setSocketAddress(addr);
     71         return pack;
     72         
     73     }
     74     //切屏
     75     private List<FrameUnit> splitScreen(byte[] frameData) {
     76         //frameUnit的长度
     77         int unitLength=60*1024;
     78         //帧单元集合
     79         List<FrameUnit> list = new ArrayList<>();
     80         int count=0;
     81         //正好整除unit大小
     82         if(frameData.length % unitLength==0){
     83             count=frameData.length / unitLength;
     84         }
     85         else{
     86             count=frameData.length / unitLength +1;
     87         }
     88         //取出时间戳
     89         long timestamp=System.currentTimeMillis();
     90         for(int i=0;i<count;i++){
     91             FrameUnit unit = new FrameUnit();
     92             unit.setTimestamp(timestamp);
     93             unit.setCount(count);
     94             unit.setIndex(i);
     95             //如果不是最后一帧单元,大小为60k;
     96             if(i !=(count-1)){
     97                 unit.setLength(60*1024);
     98                 byte[] unitData=new byte[60*1024];
     99                 System.arraycopy(frameData, i*60*1024, unitData, 0, 60*1024);
    100                 unit.setUnitData(unitData);
    101             }
    102             //最后一帧处理
    103             else{
    104                 //取得最后一帧的长度
    105                 int remain=frameData.length % unitLength==0?60*1024:frameData.length % unitLength;
    106                 unit.setLength(remain);
    107                 byte[] unitData=new byte[remain];
    108                 System.arraycopy(frameData, i*60*1024, unitData, 0, remain);
    109                 unit.setUnitData(unitData);
    110             }
    111             list.add(unit);
    112         }
    113     
    114         return list;
    115     }
    116     //抓取一屏画面
    117     private byte[] catchOneScreen(boolean zip) {
    118         try {
    119             BufferedImage image = robot.createScreenCapture(rect);
    120             ByteArrayOutputStream bos = new ByteArrayOutputStream();
    121             ImageIO.write(image, "jpg", bos);
    122             //原生数据
    123             byte[] rawrate=bos.toByteArray();
    124             //需要压缩
    125             if(zip){
    126                 ByteArrayOutputStream bos0 = new ByteArrayOutputStream();
    127                 ZipOutputStream zos=new ZipOutputStream(bos0);
    128                 zos.putNextEntry(new ZipEntry("0001"));
    129                 zos.write(rawrate);
    130                 zos.close();
    131                 bos0.close();
    132                 //直接返回该数据,后面不再执行
    133                 return bos0.toByteArray();
    134             }
    135             return rawrate;
    136         } catch (Exception e) {
    137             e.printStackTrace();
    138         }
    139         return null;
    140     }
    141 }

    2、客户端

      1 public class StudentMain {
      2 
      3     public static void main(String[] args) {
      4         StudentUI ui = new StudentUI();
      5         new ReceiverThread(ui).start();
      6     }
      7 
      8 }
      9 
     10 public class ReceiverThread extends Thread {
     11     // 存放所有帧单元的集合
     12     private Map<Integer, FrameUnit> map = new HashMap<>();
     13     private StudentUI ui;
     14     private DatagramSocket socket;
     15 
     16     public ReceiverThread(StudentUI ui) {
     17         try {
     18             this.ui = ui;
     19             socket = new DatagramSocket(9999);
     20         } catch (SocketException e) {
     21             e.printStackTrace();
     22         }
     23     }
     24 
     25     public void run() {
     26         // 数据缓存区
     27         byte[] buf = new byte[60 * 1024 + 14];
     28         DatagramPacket pack = new DatagramPacket(buf, buf.length);
     29         try {
     30             while (true) {
     31                 socket.receive(pack);
     32                 // 解析数据报包成FrameUnit
     33                 FrameUnit unit = parsePack(pack);
     34                 // 处理帧单元
     35                 processUnit(unit);
     36             }
     37         } catch (IOException e) {
     38             e.printStackTrace();
     39         }
     40     }
     41 
     42     // 解析数据包,解析帧单元
     43     private FrameUnit parsePack(DatagramPacket pack) {
     44         // 缓冲区数据,含有header
     45         byte[] bufData = pack.getData();
     46         FrameUnit unit = new FrameUnit();
     47         // 处理时间戳
     48         long timestamp = bytesUtil.byte2long(bufData);
     49         unit.setTimestamp(timestamp);
     50         // frameUnit个数
     51         int count = bufData[8];
     52         unit.setCount(count);
     53         // frame索引
     54         int index = bufData[9];
     55         unit.setIndex(index);
     56         // 数据长度
     57         byte[] bytelength = new byte[4];
     58         System.arraycopy(bufData, 10, bytelength, 0, 4);
     59         int dataLen = bytesUtil.byte2int(bytelength);
     60         unit.setLength(dataLen);
     61         // 图像数据处理
     62         byte[] unitData = new byte[dataLen];
     63         System.arraycopy(bufData, 14, unitData, 0, dataLen);
     64         unit.setUnitData(unitData);
     65         return unit;
     66     }
     67 
     68     // 处理帧单元
     69     private void processUnit(FrameUnit unit) {
     70         // 如果集合为空,没有帧单元数据
     71         if (map.isEmpty()) {
     72             map.put(unit.getIndex(), unit);
     73         } else {
     74             // 提取map中存放的帧单元的时间戳
     75             long oldTime = map.values().iterator().next().getTimestamp();
     76             long currTime = unit.getTimestamp();
     77             // 同一帧
     78             if (oldTime == currTime) {
     79                 map.put(unit.getIndex(), unit);
     80             }
     81             // 新帧单元
     82             else if (currTime > oldTime) {
     83                 map.clear();
     84                 map.put(unit.getIndex(), unit);
     85             }
     86             // 老帧单元迟到,直接丢弃
     87             else {
     88             }
     89         }
     90         // 处理frame
     91         prcessFrame(true);
     92     }
     93 
     94     // 判断是否集齐了所有帧单元,处理称为一帧
     95     private void prcessFrame(boolean zip) {
     96         try {
     97             int count = map.values().iterator().next().getCount();
     98             int size = map.size();
     99             // 集齐了所有帧单元
    100             if (count == size) {
    101                 ByteArrayOutputStream bos = new ByteArrayOutputStream();
    102                 for (int i = 0; i < count; i++) {
    103                     FrameUnit unit = map.get(i);
    104                     bos.write(unit.getUnitData());
    105                 }
    106                 // 得到一屏幕画面的帧数据
    107                 byte[] frameData = bos.toByteArray();
    108                 if (zip) {
    109                     ByteArrayOutputStream bos0 = new ByteArrayOutputStream();
    110                     ByteArrayInputStream bis = new ByteArrayInputStream(frameData);
    111                     ZipInputStream zis = new ZipInputStream(bis);
    112                     zis.getNextEntry();
    113                     byte[] buf = new byte[1024];
    114                     int len = -1;
    115                     while ((len=zis.read(buf)) != -1) {
    116                         bos0.write(buf, 0, len);
    117                     }
    118                     zis.close();
    119                     // 解压数据
    120                     frameData = bos0.toByteArray();
    121                 }
    122                 ui.updateUI(frameData);
    123                 map.clear();
    124             }
    125 
    126         } catch (Exception e) {
    127         }
    128     }
    129 
    130 }
    131 
    132 
    133 public class StudentUI extends JFrame{
    134 
    135     private static final long serialVersionUID = 2084514325030688532L;
    136     //标签字段
    137     private JLabel lbl;
    138     public StudentUI(){
    139         init();
    140         this.setVisible(true);
    141     }
    142     private void init() {
    143         this.setTitle("学生端");
    144         this.setLayout(null);
    145         this.setBounds(0, 0, 1366, 768);
    146         
    147         lbl=new JLabel();
    148         lbl.setBounds(0, 0, 1366, 768);
    149         this.add(lbl);
    150         
    151         this.addWindowListener(new WindowAdapter() {
    152             @Override
    153             public void windowClosing(WindowEvent e) {
    154                 System.exit(-1);
    155             }
    156         });
    157     }
    158     //更新UI
    159     public void updateUI(byte[] frameData){
    160         try {
    161             ByteArrayInputStream bis = new ByteArrayInputStream(frameData);
    162             BufferedImage image = ImageIO.read(bis);
    163             ImageIcon icon = new ImageIcon(image);
    164             lbl.setIcon(icon);
    165         } catch (Exception e) {
    166         }
    167     
    168 }
    169 }

    3、工具类

    public class bytesUtil {
        //字节数组转成int
        public static int byte2int(byte[] arr){
            int i0=arr[0] & 0xff;
            int i1=(arr[1] & 0xff)<<8;
            int i2=(arr[2] & 0xff)<<16;
            int i3=(arr[3] & 0xff)<<24;
            return i0 |i1|i2|i3;
        }
        //字节数组转成long
        public static long byte2long(byte[] arr){
            long i0=arr[0] & 0xffL;
            long i1=(arr[1] & 0xffL)<<8;
            long i2=(arr[2] & 0xffL)<<16;
            long i3=(arr[3] & 0xffL)<<24;
            long i4=(arr[4] & 0xffL)<<32;
            long i5=(arr[5] & 0xffL)<<40;
            long i6=(arr[6] & 0xffL)<<48;
            long i7=(arr[7] & 0xffL)<<56;
            return i0 | i1 | i2 | i3 | i4 | i5 | i6 | i7;
        }
        /**
         * 将整数转换成字节数组
         */
        public static byte[] int2ByteArr(int i){
            byte[] bytes = new byte[4] ;
            bytes[0] = (byte)(i >> 0) ;
            bytes[1] = (byte)(i >> 8) ;
            bytes[2] = (byte)(i >> 16) ;
            bytes[3] = (byte)(i >> 24) ;
            return bytes ;
        }
        /**
         * 将长整数转换成字节数组
         */
        public static byte[] long2ByteArr(long i){
            byte[] bytes = new byte[8] ;
            bytes[0] = (byte)(i >> 0) ;
            bytes[1] = (byte)(i >> 8) ;
            bytes[2] = (byte)(i >> 16) ;
            bytes[3] = (byte)(i >> 24) ;
            bytes[4] = (byte)(i >> 32) ;
            bytes[5] = (byte)(i >> 40) ;
            bytes[6] = (byte)(i >> 48) ;
            bytes[7] = (byte)(i >> 56) ;
            return bytes ;
        }
    }
    
    public class FrameUnit {
        private long timestamp;
        private int count;
        private int index;
        private int length;
        private byte[] unitData;
        public long getTimestamp() {
            return timestamp;
        }
        public void setTimestamp(long timestamp) {
            this.timestamp = timestamp;
        }
        public int getCount() {
            return count;
        }
        public void setCount(int count) {
            this.count = count;
        }
        public int getIndex() {
            return index;
        }
        public void setIndex(int index) {
            this.index = index;
        }
        public int getLength() {
            return length;
        }
        public void setLength(int length) {
            this.length = length;
        }
        public byte[] getUnitData() {
            return unitData;
        }
        public void setUnitData(byte[] unitData) {
            this.unitData = unitData;
        }    
    }
  • 相关阅读:
    托付和事件的使用
    在使用supervisord 管理tomcat时遇到的小问题
    无法安装vmware tools的解决方PLEASE WAIT! VMware Tools is currently being installed on your system. Dependin
    (转)Openlayers 2.X加载高德地图
    (转)openlayers实现在线编辑
    (转) Arcgis for js加载百度地图
    (转)Arcgis for js加载天地图
    (转) 基于Arcgis for Js的web GIS数据在线采集简介
    (转) Arcgis for js之WKT和GEOMETRY的相互转换
    (转)Arcgis for Js之Graphiclayer扩展详解
  • 原文地址:https://www.cnblogs.com/yihaifutai/p/6869641.html
Copyright © 2020-2023  润新知