1.Java接收UDP数据解码主要使用到以下三个方法:
(1)
public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer>
(2)
public static ByteBuffer wrap(byte[] array,int offset, int length)
{
try {
return new HeapByteBuffer(array, offset, length);
} catch (IllegalArgumentException x) {
throw new IndexOutOfBoundsException();
}
}
(3)
public final ByteBuffer order(ByteOrder bo) {
bigEndian = (bo == ByteOrder.BIG_ENDIAN);
nativeByteOrder =
(bigEndian == (Bits.byteOrder() == ByteOrder.BIG_ENDIAN));
return this;
}
以上方法都是Java编译工具自带的,本文使用的编译工具是IDE。
2.代码示例如下所示:
public ArrayList<DeviceStatus> analysis(DatagramPacket packet) {
byte[] buffer = packet.getData();// 接收到的UDP数据,然后解码
short head = ByteBuffer.wrap(buffer, 0, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();//帧头0x13ec
if(head == 0x13ec)/*接收服务状态格式数据并解析*/
{
NetWorkState netWorkState = UdpCache.getDeviceStatusData();
byte send_cont = ByteBuffer.wrap(buffer, 2, 1).get();//帧序列号0~255
byte recoding_state = ByteBuffer.wrap(buffer, 3, 1).order(ByteOrder.BIG_ENDIAN).get();//录音状态
int self_server_ip = ByteBuffer.wrap(buffer,4,4).order(ByteOrder.BIG_ENDIAN).getInt();//本地服务IP
int far_server_ip = ByteBuffer.wrap(buffer,8,4).order(ByteOrder.BIG_ENDIAN).getInt();//远端服务IP
int multicast_ip = ByteBuffer.wrap(buffer,12,4).order(ByteOrder.BIG_ENDIAN).getInt();//组播地址
int network_ip = ByteBuffer.wrap(buffer,16,4).order(ByteOrder.BIG_ENDIAN).getInt();//网管地址
int pc_worktop_ip = ByteBuffer.wrap(buffer,20,4).order(ByteOrder.BIG_ENDIAN).getInt();//操作台地址
int bit_ip = ByteBuffer.wrap(buffer,24,4).order(ByteOrder.BIG_ENDIAN).getInt();//BIT地址
int self_port = ByteBuffer.wrap(buffer,28,4).order(ByteOrder.LITTLE_ENDIAN).getInt();//本地端口号
int far_port = ByteBuffer.wrap(buffer,32,4).order(ByteOrder.LITTLE_ENDIAN).getInt();//远端服务器端口号
int web_port = ByteBuffer.wrap(buffer,36,4).order(ByteOrder.LITTLE_ENDIAN).getInt();//网管端口
int pc_port = ByteBuffer.wrap(buffer,40,4).order(ByteOrder.LITTLE_ENDIAN).getInt();//操作台端口
int bit_port = ByteBuffer.wrap(buffer,44,4).order(ByteOrder.LITTLE_ENDIAN).getInt();//BIT端口号
String version = new String(Arrays.copyOfRange(buffer,48,48 + 8)).trim();//软件版本v3.00
int online_state = ByteBuffer.wrap(buffer,56,4).order(ByteOrder.LITTLE_ENDIAN).getInt();//设备在线状态
byte ser_online_kun_it = ByteBuffer.wrap(buffer,60,1).order(ByteOrder.BIG_ENDIAN).get();//主副服务器及便携设备在线状态
byte a_employ = ByteBuffer.wrap(buffer,61,1).get();//A型终端信道使用标志,空闲0xFF,占用0或32
byte d_employ = ByteBuffer.wrap(buffer,62,1).get();//对讲终端信道占用标志,空闲0xFF,占用时为设备编号
byte playback = ByteBuffer.wrap(buffer,63,1).order(ByteOrder.BIG_ENDIAN).get();//回放模式,为1时回放,2为回演,0时不操作
byte connect_net_state = ByteBuffer.wrap(buffer,64,1).order(ByteOrder.BIG_ENDIAN).get();//联网状态
byte server_id = ByteBuffer.wrap(buffer,65,1).order(ByteOrder.BIG_ENDIAN).get();//服务软件ID号
short end = ByteBuffer.wrap(buffer, 66, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();//帧尾0x13ec
//将接收到的数据放入对象netWorkState中
netWorkState.setHead(head);
netWorkState.setSend_cont(send_cont);
netWorkState.setRecoding_state(recoding_state);
netWorkState.setSelf_server_ip(ByteUtils.intToIp(self_server_ip));
netWorkState.setFar_server_ip(ByteUtils.intToIp(far_server_ip));
netWorkState.setMulticast_ip(ByteUtils.intToIp(multicast_ip));
netWorkState.setNetwork_ip(ByteUtils.intToIp(network_ip));
netWorkState.setPc_worktop_ip(ByteUtils.intToIp(pc_worktop_ip));
netWorkState.setBit_ip(ByteUtils.intToIp(bit_ip));
netWorkState.setSelf_port(self_port);
netWorkState.setFar_port(far_port);
netWorkState.setWeb_port(web_port);
netWorkState.setPc_port(pc_port);
netWorkState.setBit_port(bit_port);
netWorkState.setVersion(version.trim());
netWorkState.setOnline_state(online_state);
netWorkState.setSer_online_kun_it(ser_online_kun_it);
netWorkState.setA_employ(a_employ);
netWorkState.setD_employ(d_employ);
netWorkState.setPlayback(playback);
netWorkState.setConnect_net_state(connect_net_state);
netWorkState.setServer_id(server_id);
netWorkState.setEnd(end);
}
/**---------------------------------------------------------------------------------------------------------**/
//接收回执指令帧数据
if (head == 0x11ea){
CommandReceipt commandReceipt = UdpCache.getCommandReceiptData();
byte deviceNum = ByteBuffer.wrap(buffer,2,1).order(ByteOrder.BIG_ENDIAN).get();//设备编号
byte frameNum = ByteBuffer.wrap(buffer,3,1).order(ByteOrder.BIG_ENDIAN).get();//帧序列号
byte receiptClass = ByteBuffer.wrap(buffer,4,1).order(ByteOrder.BIG_ENDIAN).get();//回执类别
byte commandMeaning = ByteBuffer.wrap(buffer,5,1).order(ByteOrder.BIG_ENDIAN).get();//指令含义
short backups_1 = ByteBuffer.wrap(buffer,6,2).order(ByteOrder.LITTLE_ENDIAN).getShort();//备份1
byte[] fileName = Arrays.copyOfRange(buffer,8,32 + 8);//文件名
long frameLong = ByteBuffer.wrap(buffer,40,8).order(ByteOrder.LITTLE_ENDIAN).getLong();//帧长度
long playSeat = ByteBuffer.wrap(buffer,48,8).order(ByteOrder.LITTLE_ENDIAN).getLong();//当前播放位置
short backups_2 = ByteBuffer.wrap(buffer,56,2).order(ByteOrder.LITTLE_ENDIAN).getShort();//备份2
short frameEnd = ByteBuffer.wrap(buffer,58,2).order(ByteOrder.LITTLE_ENDIAN).getShort();//帧尾
commandReceipt.setFrame(head);
commandReceipt.setDevice_num(deviceNum);
commandReceipt.setFrame_num(frameNum);
commandReceipt.setReceipt_class(receiptClass);
commandReceipt.setCommand_meaning(commandMeaning);
commandReceipt.setBackups1(backups_1);
commandReceipt.setFile_name(fileName);
commandReceipt.setFrame_long(frameLong);
commandReceipt.setPlay_set(playSeat);
commandReceipt.setBackups2(backups_2);
commandReceipt.setFrame_end(frameEnd);
System.out.println("接收回执数据:" + commandReceipt.getFile_name());
}
/**---------------------------------------------------------------------------------------------------------**/
ArrayList<DeviceStatus> deviceStatuses = new ArrayList<DeviceStatus>();//定义数组列表deviceStatuses存放设备状态信息
if(head == 0x15ef) //接收终端状态格式数据
{
WebWorkState webWorkState = UdpCache.getDeviceStatusData1();
byte device_number = ByteBuffer.wrap(buffer,2,1).order(ByteOrder.BIG_ENDIAN).get();//设备编号
byte serial_number = ByteBuffer.wrap(buffer,3,1).order(ByteOrder.BIG_ENDIAN).get();//帧序列号
int online_state = ByteBuffer.wrap(buffer,4,4).order(ByteOrder.LITTLE_ENDIAN).getInt();//设备在线状态
byte[] SystemStatus = Arrays.copyOfRange(buffer,8,1452 + 8);//系统所有设备工作状态(33x44字节)
short reserve = ByteBuffer.wrap(buffer, 1460, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();//备份
short backend = ByteBuffer.wrap(buffer, 1462, 2).order(ByteOrder.LITTLE_ENDIAN).getShort();//帧尾
//定义数组列表deviceStatuses存放设备状态信息
// ArrayList<DeviceStatus> deviceStatuses = new ArrayList<DeviceStatus>();
for(int i = 0;i < 33;i++)
{
DeviceStatus deviceStatus = new DeviceStatus();
deviceStatus.setName("" + i);
deviceStatus.setPattern(ByteBuffer.wrap(SystemStatus,44 * i,1).get());//通讯模式
deviceStatus.setRecord(ByteBuffer.wrap(SystemStatus,44 * i + 1,1).get());//录音状态
deviceStatus.setOn_link(ByteBuffer.wrap(SystemStatus,44 * i + 2,1).get());//网络连接回执状态
deviceStatus.setWork(ByteBuffer.wrap(SystemStatus,44 * i + 3,1).get());//运行状态
deviceStatus.setX(Math.round(ByteBuffer.wrap(SystemStatus, 44 * i + 4, 4).order(ByteOrder.LITTLE_ENDIAN).getFloat() * 100 / 100f));
deviceStatus.setA(Math.round(ByteBuffer.wrap(SystemStatus, 44 * i + 8, 4).order(ByteOrder.LITTLE_ENDIAN).getFloat() * 100 / 100f));
deviceStatus.setD(Math.round(ByteBuffer.wrap(SystemStatus, 44 * i + 12, 4).order(ByteOrder.LITTLE_ENDIAN).getFloat() * 100 / 100f));
deviceStatus.setC(Math.round(ByteBuffer.wrap(SystemStatus, 44 * i + 16, 4).order(ByteOrder.LITTLE_ENDIAN).getFloat() * 100 / 100f));
deviceStatus.setSelf_ip(ByteUtils.intToIp(ByteBuffer.wrap(SystemStatus, 44 * i + 20, 4).order(ByteOrder.BIG_ENDIAN).getInt()));
deviceStatus.setServer_ip1(ByteUtils.intToIp(ByteBuffer.wrap(SystemStatus, 44 * i + 24, 4).order(ByteOrder.BIG_ENDIAN).getInt()));
deviceStatus.setBit_ip(ByteUtils.intToIp(ByteBuffer.wrap(SystemStatus, 44 * i + 28, 4).order(ByteOrder.BIG_ENDIAN).getInt()));
deviceStatus.setGroup_ip(ByteUtils.intToIp(ByteBuffer.wrap(SystemStatus, 44 * i + 32, 4).order(ByteOrder.BIG_ENDIAN).getInt()));
deviceStatus.setGateway_ip(ByteUtils.intToIp(ByteBuffer.wrap(SystemStatus, 44 * i + 36, 4).order(ByteOrder.BIG_ENDIAN).getInt()));
deviceStatus.setServer_ip2(ByteUtils.intToIp(ByteBuffer.wrap(SystemStatus, 44 * i + 40, 4).order(ByteOrder.BIG_ENDIAN).getInt()));
deviceStatuses.add(deviceStatus);
}
webWorkState.setHead(head);
webWorkState.setDevice_number(device_number);
webWorkState.setSerial_number(serial_number);
webWorkState.setOnline_state(online_state);
webWorkState.setSystemStatus(deviceStatuses);
webWorkState.setReserve(reserve);
webWorkState.setBackend(backend);
//System.out.println("接收的数据:" + webWorkState.getSystemStatus());
}
return deviceStatuses;
}
3.Java发送UDP数据时需要注意的是对发送数据的组帧和大小端问题,要把对象序列化到数组中去,然后调用发送的方法发送数据,代码示例如下所示:
/**-----------------------------------------------------------------------------------------------------------------**/
/**
* 实现设备状态信息显示
* @param request
* @param map
* @return
*/
/**-----------------------------------------------------------------------------------------------------------------**/
@RequestMapping("/info")
public String info(HttpServletRequest request,ModelMap map){
WebCommand webCommand = new WebCommand();//实列化对象
UdpSimpleClient udpSimpleClient = new UdpSimpleClient();//实列化发送方法接口对象
/**************************************************************************/
/**
* 查询终端上报帧格式数据
* */
/**************************************************************************/
//定义数据类型值
short head = 0x14ed;
byte num = 0x21;
byte Num = 0;
Num++;
byte clas = 0x1D;//指令类别
byte matter = 0x54;//指令含义,T的ascii为84十六进制为0x54,即终端0x54
Short seat = 0x0000;
byte[] object = new byte[32];//操作目标
short reserve = 0x0000;//备份
short end = 0x13ec;//帧尾
/**************************************************************************/
//将数据放入webCommand对象中
webCommand.setHead(head);
webCommand.setCarNum(num);
webCommand.setSendCnt(Num);
webCommand.setClasses(clas);
webCommand.setMatter(matter);
webCommand.setPlaySeat(seat);
webCommand.setObjective(object);
webCommand.setReserve(reserve);
webCommand.setBackEnd(end);
/**************************************************************************/
// 对象序列化到字节数组
ByteBuffer byteBuffer = ByteBuffer.allocate(44).order(ByteOrder.LITTLE_ENDIAN);//小端序列
byteBuffer.putShort(webCommand.getHead());
byteBuffer.put(webCommand.getCarNum());
byteBuffer.put(webCommand.getSendCnt());
byteBuffer.put(webCommand.getClasses());
byteBuffer.put(webCommand.getMatter());
byteBuffer.putShort(webCommand.getPlaySeat());
byteBuffer.put(webCommand.getObjective());
byteBuffer.putShort(webCommand.getReserve());
byteBuffer.putShort(webCommand.getBackEnd());
byte[] array = byteBuffer.array();
udpSimpleClient.sendMessage(array);//发送终端查询帧
/*************************************************************************************************/
/**
* 查询服务上报帧格式数据
* */
/************************************************************************************************/
//定义数据类型值
short head1 = 0x14ed;
byte num1 = 0x21;
byte Num1 = 0;
Num1++;
byte clas1 = 0x1D;//指令类别
byte matter1 = 0x53;//指令含义,S的ascii为83十六进制为0x53,即服务
Short seat1 = 0x0000;
byte[] object1 = new byte[32];//操作目标
short reserve1 = 0x0000;//备份
short end1 = 0x13ec;//帧尾
/**************************************************************************/
//将数据放入webCommand对象中
webCommand.setHead(head1);
webCommand.setCarNum(num1);
webCommand.setSendCnt(Num1);
webCommand.setClasses(clas1);
webCommand.setMatter(matter1);
webCommand.setPlaySeat(seat1);
webCommand.setObjective(object1);
webCommand.setReserve(reserve1);
webCommand.setBackEnd(end1);
/**************************************************************************/
// 对象序列化到字节数组
ByteBuffer byteBuffer1 = ByteBuffer.allocate(44).order(ByteOrder.LITTLE_ENDIAN);//小端序列
byteBuffer1.putShort(webCommand.getHead());
byteBuffer1.put(webCommand.getCarNum());
byteBuffer1.put(webCommand.getSendCnt());
byteBuffer1.put(webCommand.getClasses());
byteBuffer1.put(webCommand.getMatter());
byteBuffer1.putShort(webCommand.getPlaySeat());
byteBuffer1.put(webCommand.getObjective());
byteBuffer1.putShort(webCommand.getReserve());
byteBuffer1.putShort(webCommand.getBackEnd());
byte[] array1 = byteBuffer.array();
udpSimpleClient.sendMessage(array1);
System.out.println("Data:" +array1);
/**************************************************************************/
/**
* 获取终端上报帧格式数据
* */
/**************************************************************************/
//必须先发送命令,再实例化获取数据
NetWorkState netWorkState = UdpCache.getDeviceStatusData();
WebWorkState webWorkState = UdpCache.getDeviceStatusData1();
UdpServer udpServer = new UdpServer();
ArrayList<DeviceStatus> analysis = udpServer.analysis(packet);
//按位与;作用:清零和取特定值,按位获取32个终端设备在线状态,
int result = webWorkState.getOnline_state();
byte server_state = netWorkState.getSer_online_kun_it();
int b[] = new int[33];
for (int i=0;i<33;i++)
{
if (i < 32)
{
b[i] = (result >> i) & 0x01;
}
else
{
b[i] = (server_state >> 2) & 0x01;
}
}
map.put("state",b);
/*----------------------------------------------------*/
//获取系统时间
Date DateTime = new Date();
SimpleDateFormat DateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String nowTime = DateTimeFormat.format(DateTime);
map.put("maptime",nowTime);
/*----------------------------------------------------*/
map.put("map1", analysis);
return "info";
}