UDP 在無線通信中用處非常之廣, 比如某個終端硬件採集數據, 會使用UDP的方式進行通信。 比如這是我們當前的一個需求架構示意圖:
圖: 採用UDP協議的產品架構示意圖
解釋:
① 表示GPS向Server傳輸數據, 這個就是【終端GPS所在公司】提供的協議接口
② Server向GPS發送命令, 大部分是配置相關的服務, 或者升級命令,目前大體需要這樣的功能,依然是【終端GPS所在公司】提供的接口:
- 設置回傳週期時間
- 設置指定傳輸的數據服務器IP地址和端口號
- 設置自動升級包的IP地址
- 查詢所有設置接口
這些接口採用的都是UDP通信協議, 因此我在做整體架構之前做了基本的Demo以滿足後續業務需求。
本文爲UDP的一個小程序。
包括兩個部分:
1. 在本機監聽某個端口, 接受其它PC發過來的數據
2. 本機主動向其它PC的特定端口發送數據
主程序UDPApplication.java:
package cn.com.sany.udp;
/**
* 啓動UDP線程
*
*
*/
public class UDPApplication {
public static void main(String[] args)
{
int len = args.length;
if (len != 3)
{
System.out.println("用法錯誤, 正確用法如下:");
System.out.println("-p 10.0.6.217 1122 (主動模式的設置, 指明對方的端口號和IP地址)");
System.out.println("-n 10.0.6.217 1122 (被動模式的設置, 指明本地的端口號和IP地址)");
return;
}
String mode = args[0];
String ip = args[1];
String portString = args[2];
int port = 0;
try{
port = Integer.valueOf(portString);
}
catch (Exception e)
{
e.printStackTrace();
}
if(mode.equalsIgnoreCase("-p"))
{
testPositive(ip, port);
return;
}
if(mode.equalsIgnoreCase("-n"))
{
testNegtive(ip, port);
return;
}
System.out.println("用法錯誤, 正確用法如下:");
System.out.println("-p 10.0.6.217 1122 (主動模式的設置, 指明對方的端口號和IP地址)");
System.out.println("-n 10.0.6.217 1122 (被動模式的設置, 指明本地的端口號和IP地址)");
}
/**
* 測試被動接收UDP信息
* 偵聽本機所在PC的端口
*/
public static void testNegtive(String ip, int port)
{
final UDPNegtive un = new UDPNegtive(port, ip);
un.process();
}
/**
* 測試主動發送UDP信息
* 往指定的PC(即知道遠程IP以及端口)
*
*/
public static void testPositive(String ip, int port)
{
final UDPPositive up = new UDPPositive(ip, port);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true)
{
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
up.sendUdpData();
}
}
});
t.start();
}
}
主動發送的UDP程序: 本機主動向其它PC的特定端口發送數據
package cn.com.sany.udp;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* UDP主動發送
*
* 1. 明確對方的端口號, 向對方主動發送消息, 如心跳消息
* 2. 不斷接受到對方的迴應
*
*
*/
public class UDPPositive {
private boolean isStoped;
private String serverIP;
private int serverPort;
private DatagramSocket socket;
public UDPPositive(String serverIP, int serverPort)
{
this.serverIP = serverIP;
this.serverPort = serverPort;
try {
socket = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
return;
}
new Thread(new Runnable() {
@Override
public void run() {
//接收線程
//接收線程
while(!isStoped){
UDPTool.receiveData(socket);
}
}
}).start();
}
/**
* 發送消息[這裏以心跳爲例]
*/
public void sendUdpData()
{
byte[] data = new byte[]{0x30,0x30,0x00,0x00,0x01,0x5E,0x5D,0x59,0x1F,0x00,0x00,0x0E,(byte)0xA2,0x01};
UDPTool.sendData(serverIP, serverPort, data, socket);
System.out.println(socket.getLocalPort() + "本地端口");
}
}
被動接收的UDP程序: 在本機監聽某個端口, 接受其它PC發過來的數據
package cn.com.sany.udp;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* UDP被動發送消息
* 1. 不知道對方的IP
* 2. 僅僅在本地的端口接收消息
* 3. 接受到消息後, 可以發送迴應, 但這裏省略該步驟
*
*/
public class UDPNegtive {
private boolean isStoped;
private DatagramSocket socket;
public UDPNegtive(int port, String ip)
{
try {
InetAddress add = InetAddress.getByName(ip);
socket = new DatagramSocket(port, add);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void process()
{
new Thread(new Runnable() {
@Override
public void run() {
//接收線程
while(!isStoped){
UDPTool.receiveData(socket);
}
}
}).start();
}
}
本程序用到的代碼, 附調試工具NetAssis