zoukankan      html  css  js  c++  java
  • 屏幕广播

    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;
        }    
    }
  • 相关阅读:
    Asp.net Mvc 中的模型绑定
    ActionResult 之HttpGet HttpPost
    Asp.net MVC 之 ActionResult
    Amazon MWS 上传数据 (三) 提交请求
    Amazon MWS 上传数据 (二) 构造请求
    Amazon MWS 上传数据 (一) 设置服务
    linq常用
    Nacos入门
    Post 方法参数写在body中和写在url中有什么区别
    强密码(必须包含字母、数字、特殊字符,长度8到16位)
  • 原文地址:https://www.cnblogs.com/yihaifutai/p/6869641.html
Copyright © 2011-2022 走看看