首頁 > 軟體

UDP協定詳細講解

2020-06-16 16:48:27

UDP是無連線通訊協定,即在資料傳輸時,資料的傳送端和接收端不建立邏輯連線。簡單來說,當一台計算機向另外一台計算機傳送資料時,傳送端不會確認接收端是否存在,就會發出資料,同樣接收端在收到資料時,也不會向傳送端反饋是否收到資料。

由於使用UDP協定消耗資源小,通訊效率高,所以通常都會用於音訊、視訊和普通資料的傳輸例如視訊會議都使用UDP協定,因為這種情況即使偶爾丟失一兩個封包,也不會對接收結果產生太大影響。

但是在使用UDP協定傳送資料時,由於UDP的面向無連線性,不能保證資料的完整性,因此在傳輸重要資料時不建議使用UDP協定。UDP的交換過程如下圖所示。

1.1 DatagramPacket

前面介紹了UDP是一種面向無連線的協定,因此,在通訊時傳送端和接收端不用建立連線。UDP通訊的過程就像是貨運公司在兩個碼頭間傳送貨物一樣。在碼頭傳送和接收貨物時都需要使用集裝箱來裝載貨物,UDP通訊也是一樣,傳送和接收的資料也需要使用“集裝箱”進行打包,為此JDK中提供了一個DatagramPacket類,該類的範例物件就相當於一個集裝箱,用於封裝UDP通訊中傳送或者接收的資料。

想要建立一個DatagramPacket物件,首先需要了解一下它的構造方法。在建立傳送端和接收端的DatagramPacket物件時,使用的構造方法有所不同,接收端的構造方法只需要接收一個位元組陣列來存放接收到的資料,而傳送端的構造方法不但要接收存放了傳送資料的位元組陣列,還需要指定傳送端IP地址和埠號。

接下來根據API文件的內容,對DatagramPacket的構造方法進行逐一詳細地講解。

使用該構造方法在建立DatagramPacket物件時,指定了封裝資料的位元組陣列和資料的大小,沒有指定IP地址和埠號。很明顯,這樣的物件只能用於接收端,不能用於傳送端。因為傳送端一定要明確指出資料的目的地(ip地址和埠號),而接收端不需要明確知道資料的來源,只需要接收到資料即可。

使用該構造方法在建立DatagramPacket物件時,不僅指定了封裝資料的位元組陣列和資料的大小,還指定了封包的目標IP地址(addr)和埠號(port)。該物件通常用於傳送端,因為在傳送資料時必須指定接收端的IP地址和埠號,就好像傳送貨物的集裝箱上面必須標明接收人的地址一樣。

上面我們講解了DatagramPacket的構造方法,接下來對DatagramPacket類中的常用方法進行詳細地講解,如下表所示。

1.2 DatagramSocket

DatagramPacket封包的作用就如同是“集裝箱”,可以將傳送端或者接收端的資料封裝起來。然而運輸貨物只有“集裝箱”是不夠的,還需要有碼頭。在程式中需要實現通訊只有DatagramPacket封包也同樣不行,為此JDK中提供的一個DatagramSocket類。DatagramSocket類的作用就類似於碼頭,使用這個類的範例物件就可以傳送和接收DatagramPacket封包,傳送資料的過程如下圖所示。

在建立傳送端和接收端的DatagramSocket物件時,使用的構造方法也有所不同,下面對DatagramSocket類中常用的構造方法進行講解。

該構造方法用於建立傳送端的DatagramSocket物件,在建立DatagramSocket物件時,並沒有指定埠號,此時,系統會分配一個沒有被其它網路程式所使用的埠號。

該構造方法既可用於建立接收端的DatagramSocket物件,又可以建立傳送端的DatagramSocket物件,在建立接收端的DatagramSocket物件時,必須要指定一個埠號,這樣就可以監聽指定的埠。

上面我們講解了DatagramSocket的構造方法,接下來對DatagramSocket類中的常用方法進行詳細地講解。

1.3 UDP實現1.3.1 案例程式碼二:

package com.linuxmi_02;
import Java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/*
 * 使用UDP協定傳送資料
建立傳送端Socket物件
建立資料並打包
傳送資料
釋放資源
 *
 * DatagramSocket:此類表示用來傳送和接收資料,基於UDP協定的
 *
 * DatagramSocket() :建立Socket物件並隨機分配埠號
 * DatagramSocket(int port) :建立Socket物件並指定埠號
 */
public class SendDemo {
public static void main(String[] args) throws IOException  {
//建立傳送端Socket物件
DatagramSocket ds = new DatagramSocket();
//建立資料並打包
/*
 * DatagramPacket :此類表示資料包包
 * 資料 byte[]
 * 裝置的地址 ip
 * 進程的地址  埠號
  DatagramPacket(byte[] buf, int length, InetAddress address, int port)
 */
String s = "hello udp,im comming!";
byte[] bys = s.getBytes();
int length = bys.length;
InetAddress address = InetAddress.getByName("linuxmi");//傳送給當前裝置
int port = 8888;
//打包
DatagramPacket dp = new DatagramPacket(bys,length,address,port);
//傳送資料
ds.send(dp);
//釋放資源
ds.close();
}
}


package com.linuxmi_02;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/*
 * 使用UDP協定接收資料
建立接收端Socket物件
接收資料
解析資料
輸出資料
釋放資源

 */
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//建立接收端Socket物件
DatagramSocket ds = new DatagramSocket(8888);
//接收資料
//DatagramPacket(byte[] buf, int length)
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
System.out.println(1);
ds.receive(dp);//阻塞
System.out.println(2);
//解析資料
//InetAddress getAddress() : 獲取傳送端的IP物件
InetAddress address = dp.getAddress();
//byte[] getData()  :獲取接收到的資料,也可以直接使用建立包物件時的陣列
byte[] data = dp.getData();
//int getLength()  :獲取具體收到資料的長度
int length = dp.getLength();
//輸出資料
System.out.println("sender ---> " + address.getHostAddress());
//System.out.println(new String(data,0,length));
System.out.println(new String(bys,0,length));
//釋放資源
ds.close();

}
}

Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx

本文永久更新連結地址https://www.linuxidc.com/Linux/2018-08/153610.htm


IT145.com E-mail:sddin#qq.com