UDP 理論詳解
阿新 • • 發佈:2018-10-31
UDP 簡 介
- UDP 是一種高速,無連線的資料交換方式,UDP 傳送資料前並不與對方建立連線,對接收到的資料也不傳送確認訊號,傳送端不知道資料是否會正確接收,當然也不用重發,所以說 UDP 是無連線的、不可靠的一種資料傳輸協議
- UDP( User Datagram Protocol ) 使用者資料報協議,是一種無連線的協議,每個資料報都是一個獨立的資訊,包括完整的源或目的地址,它在網路上以任何可能的路徑傳往目的地,因此能否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的。
- 因為不必進行收發資料的確認,所以 UDP 的實時性更好,傳輸速率更高。有時候速度比資料完整性重要,在比如視訊會議、電話通訊等,丟失幾幀畫面、聲音是可以接受的,但在需要資料安全接受的環境下,就宜採用TCP
- 在網路質量令人不十分滿意的環境下,UDP 協議資料包丟失會比較嚴重。但是由於它不屬於連線型協議,因而具有資源消耗小,處理速度快的優點,所以通常音訊、視訊和普通資料在傳送時使用 UDP 較多,因為它們即使偶爾丟失一兩個資料包,也不會對接收結果產生太大影響。
- Java 中使用 UDP 程式設計主要使用 java.net 包下的 DatagramSocket 和 DatagramPacket 類
- 可以參考《TCP 理論詳解》
通訊示例
·接收端·
- 使用 DatagramSocket(int port) 建立socket(套間字)服務,必須指定監視的 port
- 定義資料報包(DatagramPacket),用於儲存接收到的資料
- 通過 DatagramSocket 的 receive 方法將接收的資料存入上面定義的包中
- 使用 DatagramPacket 的 getData 方法,提取資料
- DatagramPacket 關閉資源
package com.lct.udp; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; import java.nio.charset.Charset; import java.util.Date; /** * Created by Administrator on 2018/10/14 0014. * UDP 接收端 */ public class UdpServer { public static void main(String[] args) { udpReceive(); } /** * Udp 監聽埠資料 */ public static void udpReceive() { DatagramSocket datagramSocket = null; /** 資料接收大小設定為1024位元組,超出部分是接收不到的 */ byte[] buffer = new byte[1024]; DatagramPacket datagramPacket; try { /** * DatagramSocket(int port, InetAddress laddr):建立一個DatagramSocket例項,並將該物件繫結到指定IP地址、指定埠。 * DatagramSocket(int port):建立一個DatagramSocket例項,並將該物件繫結到本機預設IP地址、指定埠。 * */ datagramSocket = new DatagramSocket(8080); datagramPacket = new DatagramPacket(buffer, buffer.length); /** * setSoTimeout(int timeout):設定 DatagramSocket 的 receive(DatagramPacket p) 方法 * 阻塞監聽埠時的超時時間,單位毫秒, * 當 receive 方法阻塞監聽埠超過指定的時間時,丟擲異常:java.net.SocketTimeoutException: Receive timed out */ /*datagramSocket.setSoTimeout(60 * 1000);*/ /** 接收端迴圈監聽*/ while (true) { System.out.println(new Date() + " :開始監聽埠" + Thread.currentThread().getName()); /**阻塞監聽埠*/ datagramSocket.receive(datagramPacket); /**讀取資料*/ String message = new String(datagramPacket.getData(), 0, datagramPacket.getLength(), Charset.forName("UTF-8")); System.out.println("監聽到資料:" + message); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { /**如果傳送異常,關閉操作*/ if (datagramSocket != null) { if (!datagramSocket.isConnected()) { datagramSocket.disconnect(); } if (!datagramSocket.isClosed()) { datagramSocket.close(); } } } } }
·傳送端·
- 使用 DatagramSocket 建立 socket(套間字)服務,可以指定埠,也可讓它自動分配
- 將資料打包到 DatagramPacket 中
- 通過 socket 服務傳送打包好的 DatagramPacket(send() 方法
- socket 服務關閉資源
package com.lct.udp;
import java.io.IOException;
import java.net.*;
/**
* Created by Administrator on 2018/10/14 0014.
* Udp 傳送端
*/
public class UcpClient {
public static void main(String[] args) {
/**
* 使用 3 個執行緒傳送訊息,模擬 多個客戶端操作
*/
for (int i = 0; i < 3; i++) {
new Thread() {
@Override
public void run() {
sendUdpMessage();
}
}.start();
}
}
/**
* 傳送 Udp 訊息
*/
public static void sendUdpMessage() {
DatagramSocket datagramSocket = null;
try {
/** 例項化資料報套接字*/
datagramSocket = new DatagramSocket();
/**將被髮送的資料轉為位元組陣列,同時指定編碼*/
String msg = "修長城的民族!" + Thread.currentThread().getName();
byte[] msgBytes = msg.getBytes("UTF-8");
/** InetAddress:指定 UDP 接收端的 IP 地址*/
InetAddress inetAddress = InetAddress.getByName("192.168.1.20");
/**
* DatagramPacket(byte buf[], int length,InetAddress address, int port)
* buf[]:被髮送的資料
* length:指定 buf[] 中 [0,length]的資料進行傳送
* address:udp 接收端的地址
* port:udp 接收端監聽的埠
*/
DatagramPacket datagramPacket = new DatagramPacket(msgBytes, msgBytes.length, inetAddress, 8080);
/**傳送資料*/
datagramSocket.send(datagramPacket);
System.out.println("訊息傳送結束..............." + Thread.currentThread().getName());
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
/**操作結束,釋放 datagramSocket,並關閉*/
if (datagramSocket != null) {
if (!datagramSocket.isConnected()) {
datagramSocket.disconnect();
}
if (!datagramSocket.isClosed()) {
datagramSocket.close();
}
}
}
}
}
udp 接收端輸出如下:
Sun Oct 14 11:43:40 CST 2018 :開始監聽埠main
監聽到資料:修長城的民族!Thread-0
Sun Oct 14 11:43:42 CST 2018 :開始監聽埠main
監聽到資料:修長城的民族!Thread-1
Sun Oct 14 11:43:42 CST 2018 :開始監聽埠main
監聽到資料:修長城的民族!Thread-2
Sun Oct 14 11:43:42 CST 2018 :開始監聽埠mainudp 傳送端輸出如下:
訊息傳送結束...............Thread-1
訊息傳送結束...............Thread-0
訊息傳送結束...............Thread-2
網路程式設計
- 技術日新月異,目前網路程式設計最為流行的當屬 Netty,Java 網路程式設計發展歷程:
JDK 1.4 以前:java.net + java.io——即平時所使用的簡單的 TCP 、UDP 程式設計
JDK 1.4 及以後:java.nio
當下流行:JBoos 的 Netty 庫、Apache 的 Mina 等