2021-05-12 14:32:11
UDP協定詳細講解
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
相關文章