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等问题。