自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

基于UDP的網(wǎng)絡(luò)通信之屏幕共享

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
UDP是一種用途廣泛的網(wǎng)絡(luò)傳輸協(xié)議,發(fā)送方只管發(fā)送數(shù)據(jù)出去,而不管是否能夠送達(dá)。

[[119951]]

UDP是一種用途廣泛的網(wǎng)絡(luò)傳輸協(xié)議,發(fā)送方只管發(fā)送數(shù)據(jù)出去,而不管是否能夠送達(dá)。

應(yīng)用范圍:有時(shí)候因?yàn)榫W(wǎng)絡(luò)問(wèn)題,接收方可能會(huì)丟失部分?jǐn)?shù)據(jù),但是并不影響程序的功能。例如視頻直播的時(shí)候有一些數(shù)據(jù)丟失了,最多就是卡頓一下,并不會(huì)造成功能很大的影響。

對(duì)于發(fā)送者而言,需要有一個(gè)發(fā)送者的地址與端口,也需要知道要發(fā)到哪個(gè)地址的哪個(gè)端口。同時(shí)還需要一個(gè)socket傳送數(shù)據(jù)。

在這里,可以將他們形象的比喻成郵政系統(tǒng)。

發(fā)送者就是寄件人,接收者就是收件人,而傳遞著就是郵遞員。

  1. // 創(chuàng)建一個(gè)發(fā)送者(發(fā)件人)   
  2. SocketAddress sender = new InetSocketAddress("127.0.0.1", 912);   
  3. // 創(chuàng)建一個(gè)接收者(收件人)   
  4. SocketAddress receiver = new InetSocketAddress("127.0.0.1", 913);   
  5. // 創(chuàng)建一個(gè)傳遞者(郵遞員)   
  6. DatagramSocket socket = new DatagramSocket(sender);   

而對(duì)于寄件人而言,他需要將要寄的東西用一個(gè)包裝裝好,也就是包裹一樣。然后再交給郵遞員送出去。

  1. byte[] msg="Hello!".getBytes();   
  2. DatagramPacket m = new DatagramPacket(msg, msg.length, receiver);   
  3. socket.send(m);   

對(duì)于接收者而言,他需要知道去哪里取數(shù)據(jù),郵遞員是誰(shuí),收到了一個(gè)包裹。

  1. // 創(chuàng)建接收對(duì)象(收件人)   
  2. SocketAddress receiver = new InetSocketAddress("127.0.0.1", 913);   
  3. // 得到消息接收的socket(郵遞員)   
  4. DatagramSocket socket = new DatagramSocket(receiver);   
  5. // 定義好包裹   
  6. DatagramPacket data = new DatagramPacket(buf, buf.length);   
  7. // 用socket將數(shù)據(jù)包裹接收進(jìn)來(lái)   
  8. socket.receive(data);    

這其中就需要定義一些協(xié)議。

UDP出了上述一對(duì)一共享,還可以以組播的方式共享數(shù)據(jù),即一對(duì)多。

這里以簡(jiǎn)單的屏幕分享為例

首先,要明確我們的目的是需要將某臺(tái)計(jì)算機(jī)的屏幕分享給其他人。

也就是將計(jì)算機(jī)屏幕截圖,再使用局域網(wǎng)組播。

由于每次發(fā)送的數(shù)組不能過(guò)大,所以截取屏幕得到的圖片需要分多次發(fā)送出去,等客戶端接收到了再拼成原圖。所以需要一個(gè)信息頭來(lái)保存圖片的基本信息以便于客戶端收到之后能順利拼回原圖。

關(guān)鍵在于如何定義這個(gè)信息頭,在接收方我們需要知道發(fā)送端傳給我們的圖片是分多少次發(fā)送過(guò)來(lái)的,也要知道總共有多少個(gè)字節(jié),還要判斷是不是因?yàn)榫W(wǎng)絡(luò)原因有部分?jǐn)?shù)據(jù)被丟棄了,那樣的話自然就無(wú)法還原數(shù)據(jù)了。

在這里,我采用的方法是:

信息頭定義如下:

第一個(gè)字節(jié)為類型,暫時(shí)用0表示圖片

第二個(gè)字節(jié)為數(shù)據(jù)組數(shù),意思是這張圖片分成了多少次發(fā)出去,在客戶端需要收到多少才能pin回來(lái)

第三個(gè)字節(jié)為隨機(jī)的一個(gè)記號(hào),用來(lái)告訴客戶端是否數(shù)據(jù)丟失了。如果有數(shù)據(jù)丟失,

則應(yīng)該丟棄相關(guān)的所有數(shù)據(jù),不能拼回原圖,則跳過(guò)這一幀。

第四個(gè)字節(jié)為實(shí)際要傳輸?shù)臄?shù)據(jù)長(zhǎng)度的位數(shù)。比如實(shí)際上是1234byte,則這個(gè)值是4

接下來(lái)的n個(gè)為長(zhǎng)度信息,比如:data[4] = 1;data[5] = 2;data[6] = 3;這就表示長(zhǎng)度為1234

每一次都發(fā)10000個(gè)實(shí)際字節(jié)數(shù)據(jù)

加上10個(gè)左右的頭部信息。所以每個(gè)數(shù)組長(zhǎng)度都是10010

客戶端接收到消息之后,就要判斷是不是有數(shù)據(jù)丟失。沒(méi)有的話就會(huì)拼回原圖并顯示

接收到了這次的數(shù)據(jù)之后,如果發(fā)現(xiàn)前一組丟了部分?jǐn)?shù)據(jù),那么就要將前一組數(shù)據(jù)全部清空,然后繼續(xù)接收#p#

部分代碼如下:

發(fā)送者:

  1. package V0913;   
  2.    
  3. import java.awt.Dimension;   
  4. import java.awt.Rectangle;   
  5. import java.awt.Robot;   
  6. import java.awt.Toolkit;   
  7. import java.awt.image.BufferedImage;   
  8. import java.io.BufferedOutputStream;   
  9. import java.io.ByteArrayOutputStream;   
  10. import java.io.File;   
  11. import java.io.FileOutputStream;   
  12. import java.io.IOException;   
  13. import java.net.DatagramPacket;   
  14. import java.net.InetAddress;   
  15. import java.net.MulticastSocket;   
  16. import java.net.UnknownHostException;   
  17. import java.util.ArrayList;   
  18.    
  19. import javax.imageio.ImageIO;   
  20.    
  21. /**  
  22.  * 發(fā)送數(shù)據(jù)的線程  
  23.  *   
  24.  * @author 斌  
  25.  * @2014年9月13日  
  26.  */   
  27. public class SendThread extends Thread {   
  28.    
  29.     InetAddress inetAdd;   
  30.     MulticastSocket cast;   
  31.     byte biaoji = 0;   
  32.    
  33.     public void run() {   
  34.         try {   
  35.             // 創(chuàng)建組播地址   
  36.             inetAdd = InetAddress.getByName("230.0.0.1");   
  37.             // 創(chuàng)建組播的Socket對(duì)象   
  38.             cast = new MulticastSocket();   
  39.    
  40.             // 截屏   
  41.             Robot robot = new Robot();   
  42.             Dimension dis = Toolkit.getDefaultToolkit().getScreenSize();   
  43.    
  44.             BufferedImage image;   
  45.             while (Login.connected) {   
  46.                 // 得到屏幕截圖數(shù)據(jù)   
  47.                 image = robot.createScreenCapture(new Rectangle(dis));   
  48.                 // 將圖片轉(zhuǎn)換為byte數(shù)組   
  49.                 ByteArrayOutputStream baos = new ByteArrayOutputStream();   
  50.                 ImageIO.write(image, "png", baos);   
  51.                 byte[] data = baos.toByteArray();   
  52.    
  53.                 // new BufferedOutputStream(new FileOutputStream(new File(   
  54.                 // "data.txt"))).write(data);   
  55.    
  56.                 send(data);   
  57.                 // // 數(shù)據(jù)丟失的模擬   
  58.                 // byte dt[] = { 0, 122, 2, 1, 4, 1, 2, 3, 4 };   
  59.                 // DatagramPacket packet = new DatagramPacket(dt, dt.length,   
  60.                 // inetAdd, 9876);   
  61.                 //   
  62.                 // // 將其發(fā)送   
  63.                 // try {   
  64.                 // cast.send(packet);   
  65.                 // } catch (IOException e) {   
  66.                 // e.printStackTrace();   
  67.                 // }   
  68.    
  69.                 if (biaoji < 100) {   
  70.                     biaoji++;   
  71.                 } else {   
  72.                     biaoji = 0;   
  73.                 }   
  74.    
  75.                 Thread.sleep(30);   
  76.             }   
  77.         } catch (UnknownHostException e) {   
  78.             e.printStackTrace();   
  79.         } catch (Exception e) {   
  80.             e.printStackTrace();   
  81.         }   
  82.     }   
  83.    
  84.     public void send(byte[] data) {   
  85.         // 將data數(shù)組拆分發(fā)送   
  86.         long length = data.length;// 數(shù)據(jù)總長(zhǎng)度   
  87.         ArrayList<byte[]> list = new ArrayList<byte[]>();   
  88.         byte size = (byte) (length / 10000 + 1);// 這張圖片有多少組數(shù)據(jù)數(shù)據(jù)   
  89.         int j = 0;   
  90.         while (j < size) {   
  91.             byte[] dataTemp;   
  92.             int temp;   
  93.             if (j < size - 1) {   
  94.                 temp = 10000;   
  95.             } else {   
  96.                 temp = (int) (length % 10000);// 最后一次需要的大小   
  97.             }   
  98.             dataTemp = new byte[10010];   
  99.             dataTemp[0] = 0;// 類型   
  100.             dataTemp[1] = biaoji;// 記號(hào),接收方用來(lái)判斷是不是丟了數(shù)據(jù)   
  101.             dataTemp[2] = size;// 總共有多少組數(shù)據(jù)需要接收   
  102.             dataTemp[3] = getLength(temp);// 數(shù)據(jù)大小占了數(shù)組幾位   
  103.             for (int i = 0; i < dataTemp[3]; i++) {   
  104.                 // 將數(shù)據(jù)大小保存起來(lái)   
  105.                 dataTemp[i + 4] = getElem(temp, i);   
  106.             }   
  107.             // 每次存10000個(gè)字節(jié)數(shù)據(jù)   
  108.             for (int i = 0; i < temp; i++) {   
  109.                 dataTemp[i + 4 + dataTemp[3]] = data[j * 10000 + i];   
  110.             }   
  111.    
  112.             list.add(dataTemp);   
  113.             j++;   
  114.         }   
  115.    
  116.         // 循環(huán)發(fā)送數(shù)據(jù)   
  117.         for (int i = 0; i < list.size(); i++) {   
  118.             // 將其打包   
  119.             DatagramPacket packet = new DatagramPacket(list.get(i),   
  120.                     list.get(i).length, inetAdd, 9876);   
  121.    
  122.             // 將其發(fā)送   
  123.             try {   
  124.                 cast.send(packet);   
  125.             } catch (IOException e) {   
  126.                 e.printStackTrace();   
  127.             }   
  128.         }   
  129.         System.out.println("發(fā)送了一張圖片");   
  130.     }   
  131.    
  132.     /**  
  133.      * 獲得一個(gè)long的位數(shù)  
  134.      *   
  135.      * @param num  
  136.      * @return  
  137.      */   
  138.     private byte getLength(long num) {   
  139.         byte count = 1;   
  140.         while (num / 10 != 0) {   
  141.             num /= 10;   
  142.             count++;   
  143.         }   
  144.         return count;   
  145.     }   
  146.    
  147.     /**  
  148.      * 獲得num中第index位的數(shù)字,以0開(kāi)始計(jì)算起始位置  
  149.      *   
  150.      * @param num  
  151.      * @param index  
  152.      * @return  
  153.      */   
  154.     private byte getElem(long num, int index) {   
  155.         int length = getLength(num);   
  156.         // 最后一個(gè)   
  157.         if ((index + 1) == length) {   
  158.             return (byte) (num % 10);   
  159.         }   
  160.         long count = num;   
  161.         for (int i = 0; i < length - index - 1; i++) {   
  162.             countcount = count / 10;   
  163.         }   
  164.         countcount = count % 10;   
  165.         return (byte) count;   
  166.     }   
  167. }   

#p#接收者:

  1. package V0913;   
  2.    
  3. import java.io.IOException;   
  4. import java.net.DatagramPacket;   
  5. import java.net.InetAddress;   
  6. import java.net.MulticastSocket;   
  7. import java.util.ArrayList;   
  8.    
  9. import javax.swing.ImageIcon;   
  10.    
  11. /**  
  12.  * 接收數(shù)據(jù)的線程  
  13.  *   
  14.  * @author 斌  
  15.  * @2014年9月13日  
  16.  */   
  17. public class ReceiveThread extends Thread {   
  18.    
  19.     private MulticastSocket cast;   
  20.    
  21.     public void run() {   
  22.    
  23.         try {   
  24.             // 創(chuàng)建窗口   
  25.             MainUI mu = new MainUI();   
  26.             // 創(chuàng)建socket用來(lái)接收數(shù)據(jù)   
  27.             cast = new MulticastSocket(9876);   
  28.             // 定義組播地址   
  29.             InetAddress inetAdd = InetAddress.getByName("230.0.0.1");   
  30.             // 將socket加入該地址組   
  31.             cast.joinGroup(inetAdd);   
  32.             System.out.println("stratServer");   
  33.             while (mu.connect) {   
  34.                 ImageIcon icon = receive();   
  35.                 // 顯示在窗口上   
  36.                 if (icon != null) {   
  37.                     mu.label.setIcon(icon);   
  38.                     mu.center.repaint();   
  39.                 }   
  40.             }   
  41.         } catch (IOException e) {   
  42.             e.printStackTrace();   
  43.         }   
  44.     }   
  45.    
  46.     public ImageIcon receive() throws IOException {   
  47.    
  48.         ArrayList<byte[]> list = new ArrayList<byte[]>();   
  49.         // 創(chuàng)建數(shù)據(jù)包對(duì)象   
  50.    
  51.         byte dataTemp[] = new byte[10010];   
  52.    
  53.         long alllength = 0;   
  54.    
  55.         DatagramPacket packet = new DatagramPacket(dataTemp, dataTemp.length);   
  56.    
  57.         // 接收數(shù)據(jù)包   
  58.    
  59.         cast.receive(packet);   
  60.         // 提取頭部信息進(jìn)行解析,第0個(gè)為類型,判斷是否為0,第1個(gè)為記號(hào),第2個(gè)為多少個(gè)數(shù)據(jù)需要接受,第3個(gè)為長(zhǎng)度的長(zhǎng)度,之后接著長(zhǎng)度信息,之后再是數(shù)據(jù)   
  61.    
  62.         int biaoji = dataTemp[1];   
  63.         byte size = dataTemp[2];   
  64.         alllength += getLength(dataTemp);   
  65.         list.add(dealData(dataTemp));   
  66.    
  67.         for (int i = 1; i < size; i++) {   
  68.             packet = new DatagramPacket(dataTemp, dataTemp.length);   
  69.             // 接收數(shù)據(jù)包   
  70.             cast.receive(packet);   
  71.             if (biaoji == dataTemp[1]) {   
  72.                 list.add(dealData(dataTemp));   
  73.                 alllength += getLength(dataTemp);   
  74.             } else {   
  75.                 // ***************************************************************************************//   
  76.                 System.out.println("有數(shù)據(jù)丟了");   
  77.                 // 初始化數(shù)據(jù)   
  78.                 list.clear();   
  79.                 biaoji = dataTemp[1];   
  80.                 size = dataTemp[2];   
  81.                 i = 0;   
  82.                 list.add(dealData(dataTemp));   
  83.                 alllength = getLength(dataTemp);   
  84.             }   
  85.         }   
  86.         // 將list中的數(shù)組全部加到data中去   
  87.         byte data[] = new byte[(int) alllength];   
  88.         for (int i = 0; i < list.size(); i++) {   
  89.             byte t[] = list.get(i);   
  90.             for (int j = 0; j < t.length; j++) {   
  91.                 data[i * 10000 + j] = t[j];   
  92.             }   
  93.         }   
  94.         // new BufferedOutputStream(new FileOutputStream(new File("data.txt")))   
  95.         // .write(data);   
  96.    
  97.         // 將數(shù)據(jù)還原成圖像   
  98.         ImageIcon icon = new ImageIcon(data);   
  99.         return icon;   
  100.     }   
  101.    
  102.     /**  
  103.      * 處理收到的數(shù)據(jù),得到真正需要的數(shù)據(jù)  
  104.      *   
  105.      * @param dataTemp  
  106.      * @return  
  107.      */   
  108.     public byte[] dealData(byte dataTemp[]) {   
  109.    
  110.         int length = getLength(dataTemp);// 一般為10000   
  111.    
  112.         byte[] data = new byte[length];   
  113.         // 得到了數(shù)據(jù)長(zhǎng)度,之后開(kāi)始讀數(shù)據(jù)   
  114.         for (int i = 0; i < length; i++) {   
  115.             data[i] = dataTemp[i + dataTemp[3] + 4];   
  116.         }   
  117.         return data;   
  118.     }   
  119.    
  120.     /**  
  121.      * 獲得實(shí)際需要數(shù)據(jù)的長(zhǎng)度  
  122.      *   
  123.      * @param dataTemp  
  124.      * @return  
  125.      */   
  126.     public int getLength(byte dataTemp[]) {   
  127.         byte temp[] = new byte[dataTemp[3]];   
  128.         for (int i = 0; i < dataTemp[3]; i++) {   
  129.             temp[i] = dataTemp[i + 4];   
  130.         }   
  131.    
  132.         return getNum(temp);   
  133.     }   
  134.    
  135.     /**  
  136.      * 根據(jù)byte數(shù)組合成一個(gè)數(shù)字 如:{1,2,3,4}合成之后為1234  
  137.      *   
  138.      * @param data  
  139.      * @return  
  140.      */   
  141.     public int getNum(byte data[]) {   
  142.         int temp = 0;   
  143.         for (int i = 0; i < data.length; i++) {   
  144.             temp += data[i] * Math.pow(10, data.length - i - 1);   
  145.         }   
  146.         return temp;   
  147.     }   
  148. }   

#p#運(yùn)行效果圖如下:

 

 

發(fā)送端點(diǎn)擊開(kāi)始按鈕開(kāi)始發(fā)送截圖

 

 

接收方點(diǎn)擊開(kāi)始,開(kāi)始接受數(shù)據(jù)

 

 

由于在本地上直接測(cè)試,所以會(huì)出現(xiàn)重疊。程序中使用了jna和platform的透明效果。

責(zé)任編輯:林琳 來(lái)源: ITeye-博客
相關(guān)推薦

2025-04-07 00:55:00

RustUDP編程

2019-04-29 10:26:49

TCP網(wǎng)絡(luò)協(xié)議網(wǎng)絡(luò)通信

2020-07-06 07:52:10

Kubernetes網(wǎng)絡(luò)通信

2024-02-20 19:53:57

網(wǎng)絡(luò)通信協(xié)議

2019-09-25 08:25:49

RPC網(wǎng)絡(luò)通信

2013-03-21 11:05:14

2020-11-12 08:52:16

Python

2023-09-18 13:12:00

TCPUDP

2009-08-24 17:20:13

C#網(wǎng)絡(luò)通信TCP連接

2023-03-15 08:17:27

Kafka網(wǎng)絡(luò)通信組件

2017-01-15 17:44:56

node網(wǎng)絡(luò)通信Socket

2025-04-17 01:44:00

2010-07-01 15:45:22

網(wǎng)絡(luò)通信協(xié)議

2022-12-05 09:25:17

Kubernetes網(wǎng)絡(luò)模型網(wǎng)絡(luò)通信

2010-06-09 11:57:42

網(wǎng)絡(luò)通信協(xié)議

2010-06-14 19:13:28

網(wǎng)絡(luò)通信協(xié)議

2021-08-13 11:27:25

網(wǎng)絡(luò)通信數(shù)據(jù)

2010-06-29 10:15:31

局域網(wǎng)故障

2023-06-19 07:54:37

DotNetty網(wǎng)絡(luò)通信框架

2021-08-30 13:08:56

Kafka網(wǎng)絡(luò)通信
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)