UDP傳輸協議是一種常見的傳輸協議,但是在實際中,運用的很少,一般都是使用TCP協議,因爲TCP傳輸協議是安全可靠的傳輸協議,可以保證數據的完整性,但是對於傳輸效率而言沒有UDP高。而UDP因爲不需要保證數據傳輸可靠性,犧牲了可靠性,反而傳輸效率會高很多。對於有些場景,比如頻繁上報的心跳數據,或者車輛GPS數據,因爲丟失一條或者多條,對於整個系統的影響很小,或者說沒有,這樣的場景,在能夠保證數據傳輸效率的前提下,使用UDP可能更合適。
Java中UDP傳輸協議編程,提供了原生的API,可以很方便的通過兩個主要的類DatagramSocket和DatagramPacket來實現一個簡單的示例,下面分別給出一個數據發送和數據接收的程序代碼。
package com.xxx.huali.hualitest;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPSendTest {
public static void main(String[] args) {
DatagramSocket socket = null;
try {
socket = new DatagramSocket(10000);
byte[] data = "hello,udp\n".getBytes();
int port = 8080;
InetAddress address = InetAddress.getByName("192.168.253.101");
DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
socket.send(packet);
byte[] buffer = new byte[1024];
DatagramPacket receiver = new DatagramPacket(buffer, buffer.length);
socket.receive(receiver);
String res = new String(receiver.getData(),0,receiver.getLength());
System.out.println("response by server : "+res);
} catch (Exception e) {
e.printStackTrace();
}finally {
socket.close();
}
}
}
這個程序是用來做發送數據用的,可以理解爲一個UDP的客戶端程序,另外爲了接收服務端返回的數據,在數據發送socket.send()之後,會等待服務端返回數據,socket.receive()方法,會接收服務端返回的數據。這個程序是發送一個"hello,udp\n"的消息,然後等待服務端返回。
這裏需要注意的是,發送程序中,我們一開始構建DatagramSocket就指定了10000端口來通訊,是爲了指定在udp傳輸中,發送端使用的接口,而不是啓動10000端口來監聽,這裏容易和服務端的8080端口監聽混淆。可以這麼來理解,服務端開啓了8080監聽,我們客戶端程序連接上去,其實我們本地也需要開啓一個端口的,默認是一個隨機的端口,這裏我們通過指定一個固定的端口來通訊。
另一個程序是UDP服務端,用來接收客戶端發送的數據,並在讀取數據之後,會發送一個反饋給客戶端。服務端採用的邏輯是先socket.receive(),然後調用socket.send(),剛好和客戶端相反。服務端可能會接收很多個客戶端發送過來的數據,所以這裏採用一個線程的方式,並在線程中通過while(true)來一直等待多個客戶端程序的連接。
package com.xxx.huali.hualitest;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPReceiveTest implements Runnable {
private final int MAX_SIZE = 1024;
private final int PORT = 8080;
private DatagramSocket socket;
public static void main(String[] args) {
new Thread(new UDPReceiveTest()).start();
}
@Override
public void run() {
try {
socket = new DatagramSocket(PORT);
System.out.println("UDP server start.");
int count = 0;
while(true) {
byte[] buffer = new byte[MAX_SIZE];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String data = new String(packet.getData(),0,packet.getLength());
System.out.println("server receive data : "+data);
byte[] send = String.format("yes,udp server. %d times", count++).getBytes();
packet.setData(send);
socket.send(packet);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
socket.close();
}
}
}
運行程序,我們先啓動服務端程序,監聽8080端口,然後啓動客戶端發送數據。
實際開發中,我們可能不會手寫原生的UDP協議來做數據傳輸的項目,因爲UDP傳輸協議或者TCP傳輸協議項目,還有很多別的問題,比如多線程,IO問題,數據報文黏包拆包的問題,一般會選擇使用開源的穩定的框架來做,比如netty,mina他們現在已經很穩定,而且被廣泛使用,我們使用這些框架,只需要把重心放在數據解析或者業務邏輯中來,而不用關心多線程,IO等問題。