UDP方式的傳輸

  • 2019 年 10 月 18 日
  • 筆記

UDP

部分內容需要查文檔學習,我們需要了解下面的兩個類:java.net.DatagramSocket和java.net.DatagramPacket

java.net.DatagramSocket:

  • 此類表示用來發送和接收數據報包的套接字。它就像數據傳輸過程中的司機或者接站員一樣,它指引著數據發送的方向和傳輸到達的地方
構造方法:
  • DatagramSocket() 構造數據報套接字並將其綁定到本地主機上任何可用的埠。

  • DatagramSocket(int port, InetAddress laddr) 創建數據報套接字,將其綁定到指定的本地地址。

常用的方法:
  • send(DatagramPacket p) 從此套接字發送數據報包。

  • receive(DatagramPacket p)從此套接字接收數據報包。

  • close() 關閉此數據報套接字。

java.net.DatagramPacket:

  • 此類表示數據報包。它就像數據傳輸中的交通工具,就是它承載著數據在主機之間傳輸,這個對象將數據打了個包,裡面不光封裝了數據內容,還有數據的來源,發送數據的主機IP埠等等都一併被封裝到了裡面。
構造方法:
  • DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
    構造數據報包,用來將長度為 length 偏移量為 offset 的包發送到指定主機上的指定埠號。

  • DatagramPacket(byte[] buf, int length, InetAddress address, int port)
    構造數據報包,用來將長度為 length 的包發送到指定主機上的指定埠號。

  • DatagramPacket(byte[] buf, int length)
    構造 DatagramPacket,用來接收長度為 length 的數據包。

UDP接收端

先寫一個UDP的接收端,大概思路就是,先通過

DatagramSocket ds = new DatagramSocket(10003);

new一個對象,這個對象用來發送和接收數據包的套接字。然後通過

DatagramPacket dp = new DatagramPacket(buf, buf.length);

定義數據包,最後調用recieve函數來接收數據,並將數據封裝在數據包中。
值得注意的是發送端的發送至的IP地址及其埠必須和接收端的主機IP以及埠相對應

import java.io.IOException;  import java.net.DatagramPacket;  import java.net.DatagramSocket;    public class UdpRecieve {      public static void main(String[] args) throws IOException, IOException {            System.out.println("udp  接收端......run");          /**           * 定義一個udp的接收端,接收發送過來的數據。並顯示在螢幕上           *           * 思路:           *     1、先有udp socket服務,就是先有插座。 而且記住:接收端一定要明確埠,否則,收不到數據           *     2、接受數據。之前應該先將數據存儲到數據包中。因為數據還有解析           *     3、先定義數據包           *     4、通過數據包對象獲取數據包的內容,發送端的ip、發送端的埠、發送過來的數據           *     5、關閉資源           * */          //1、先有udp socket服務,就是先有插座。而且記住:接收端一定要明確埠,否則,收不到數據          DatagramSocket ds = new DatagramSocket(10000);            //2、接受數據。之前應該先將數據存儲到數據包中。因為數據還有解析          //3、先定義數據包          byte[] buf = new byte[1024];    //緩衝區,保存數據          DatagramPacket dp = new DatagramPacket(buf, buf.length);          ds.receive(dp); //阻塞,在接受到數據之前一直處於阻塞狀態,類似於輸入操作            //4、通過數據包對象獲取數據包的內容,發送端的ip、發送端的埠、發送過來的數據          String ip = dp.getAddress().getHostAddress();          int port = dp.getPort();          String text = new String(dp.getData(),0,dp.getLength());            System.out.println(ip+"---:---"+port+"---:---"+text);          //5、關閉資源          ds.close();      }  }  

將其裝在一個while(true)循環里,可以持續接收數據

import java.io.IOException;  import java.net.DatagramPacket;  import java.net.DatagramSocket;    public class UdpRecieve2 {      public static void main(String[] args) throws IOException, IOException {          System.out.println("udp  接收端     run");          /**           * 定義一個udp的接收端,接收發送過來的數據。並顯示在螢幕上           *           * 思路:           *     1、先有udp socket服務,就是先有插座。 而且記住:接收端一定要明確埠,否則,收不到數據           *     2、接受數據。之前應該先將數據存儲到數據包中。因為數據還有解析           *     3、先定義數據包           *     4、通過數據包對象獲取數據包的內容,發送端的ip、發送端的埠、發送過來的數據           *     5、關閉資源           * */            //1、先有udp  socket服務,就是先有插座嘛。而且記住:接收端一定要明確埠,否則,收不到數據          DatagramSocket ds = new DatagramSocket(10000);            while(true)          {              //2、接受數據。之前應該先將數據存儲到數據包中。因為數據還有解析              //3、先定義數據包              byte[] buf = new byte[1024];              DatagramPacket dp = new DatagramPacket(buf, buf.length);              ds.receive(dp); //阻塞                //4、通過數據包對象獲取數據包的內容,發送端的ip、發送端的埠、發送過來的數據              String ip = dp.getAddress().getHostAddress();              int port = dp.getPort();              String text = new String(dp.getData(),0,dp.getLength());                System.out.println(ip+":"+port+":    "+text);          }      }  }

UDP發送端

用下面這句先創建一個socket來指引數據的去向,這個裡面的參數「8888」表示的不是發送目的地主機的埠,而是發送起點的埠,表示從這個主機的8888埠發出去的。

DatagramSocket ds = new DatagramSocket(8888);

然後再用下面這句將數據內容,發送的目的地都封裝到這麼一個數據包裡面,裡面的參數buf表示位元組數組,必須是位元組數組,不能是字元串數組,buf.length無疑是傳輸的長度, InetAddress.getByName("127.255.25.1")是目的地的主機地址,這句的含義是通過ip地址獲取主機地址,10000表示目的地接收這個數據的埠,這個埠要保證沒有被其他應用佔用。

 DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("127.255.25.1"), 10000);

最後調用send函數即可完成發送

import java.io.IOException;  import java.net.DatagramPacket;  import java.net.DatagramSocket;  import java.net.InetAddress;    public class UdpSend {      public static void main(String[] args) throws IOException, IOException {            System.out.println("udp  發送端     run");            /**           * 通過查閱文檔,了解到用於UDP傳輸協議的對象是DatagramSocket           *           * 通過UDP協議發送一段文本數據           * 思路:           *     1、需要先建立UDP的socket。它具備發送和接收功能           *     2、將數據封裝到數據包中。數據包對象是DatagramPacket           *     3、使用socket對象的send方法將數據包發送出去           *     4、關閉資源           * */              //1、需要先建立UDP的socket。它具備發送和接收功能          DatagramSocket ds = new DatagramSocket(8888);            //2、將數據封裝到數據包中。數據包對象是DatagramPacket          String text = "hello udp來了!";          byte[] buf = text.getBytes();   //將數據轉成位元組數組          //將位元組數組封裝到數據包中          DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("127.255.25.1"), 10000);            //3、使用socket對象的send方法將數據包發送出去          ds.send(dp);            //4、關閉資源          ds.close();      }  }

發送鍵盤輸入的數據,這裡其實就是加了鍵盤錄入,IO流的操作

import java.io.BufferedReader;  import java.io.IOException;  import java.io.InputStreamReader;  import java.net.DatagramPacket;  import java.net.DatagramSocket;  import java.net.InetAddress;    public class UdpSend2 {      public static void main(String[] args) throws IOException, IOException {            System.out.println("udp  發送端     run");            /**           * 通過查閱文檔,了解到用於UDP傳輸協議的對象是DatagramSocket           *           * 通過UDP協議發送一段文本數據 思路:           * 1、需要先建立UDP的socket。它具備發送和接收功能           * 2、將數據封裝到數據包中。數據包對象是DatagramPacket           * 3、使用socket對象的send方法將數據包發送出去           * 4、關閉資源           */            // 1、需要先建立UDP的socket。它具備發送和接收功能          DatagramSocket ds = new DatagramSocket(9999);            // 2、將數據封裝到數據包中。數據包對象是DatagramPacket。數據來自於鍵盤錄入          BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));          String line = null;          while ((line = bufr.readLine()) != null)          {              if("over".equals(line))                  break;              byte[] buf = line.getBytes(); // 將數據轉成位元組數組              // 將位元組數組封裝到數據包中              DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("127.255.25.1"), 10000);              ds.send(dp);          }            // 4、關閉資源          ds.close();      }  }

成功示例:

發送前
在這裡插入圖片描述
從鍵盤錄入發送內容
在這裡插入圖片描述
接收端
在這裡插入圖片描述