package udptcp;
|
|
import java.util.ArrayList;
|
import java.util.List;
|
|
// ÖØÃüÃûΪPacketParser£¬±íʾÊý¾Ý°ü½âÎöÆ÷
|
public class PacketParser {
|
// Ìí¼ÓÊ®Áù½øÖÆ×Ö·ûÊý×é³£Á¿
|
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
|
// »º³åÇø×Ö½ÚÊý×é
|
private byte[] buffer = new byte[4096];
|
// µ±Ç°»º³åÇøÓÐЧÊý¾Ý³¤¶È
|
private int bufferLength = 0;
|
|
// ×·¼ÓÐÂÊý¾Ýµ½»º³åÇø
|
public void appendData(byte[] newData, int length) {
|
// ¼ì²é»º³åÇøÊÇ·ñ×ã¹»
|
if (bufferLength + length > buffer.length) {
|
// ´´½¨Ðµĸü´ó»º³åÇø
|
byte[] newBuffer = new byte[bufferLength + length];
|
// ¸´ÖÆÔÓÐÊý¾Ý
|
System.arraycopy(buffer, 0, newBuffer, 0, bufferLength);
|
buffer = newBuffer;
|
}
|
// ×·¼ÓÐÂÊý¾Ý
|
System.arraycopy(newData, 0, buffer, bufferLength, length);
|
// ¸üлº³åÇø³¤¶È
|
bufferLength += length;
|
}
|
|
// ÐÂÔö·½·¨£º×Ö½ÚÊý×éתʮÁù½øÖÆ×Ö·û´®
|
public static String bytesToHexString(byte[] bytes) {
|
if (bytes == null) return "";
|
char[] hexChars = new char[bytes.length * 2];
|
for (int j = 0; j < bytes.length; j++) {
|
int v = bytes[j] & 0xFF;
|
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
|
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
|
}
|
return new String(hexChars);
|
}
|
|
// ½âÎö»º³åÇøÖеÄËùÓÐÍêÕûÊý¾Ý°ü
|
public List<DataPacket> parsePackets() {
|
List<DataPacket> packets = new ArrayList<>();
|
int index = 0; // µ±Ç°½âÎöλÖÃË÷Òý
|
|
// ±éÀú»º³åÇø²éÕÒÍêÕûÊý¾Ý°ü
|
while (index <= bufferLength - 4) { // È·±£ÓÐ×ã¹»Êý¾Ý¼ì²é°üÍ·
|
// ¼ì²é°üÍ·±êʶ 0x55 0xAA
|
if (buffer[index] == 0x55 && (buffer[index + 1] & 0xFF) == 0xAA) {
|
// »ñÈ¡°üÀàÐÍ£¨µÚ3×Ö½Ú£©
|
int packetType = buffer[index + 2] & 0xFF;
|
// »ñÈ¡Êý¾Ý³¤¶È£¨µÚ4×Ö½Ú£©
|
int dataLenField = buffer[index + 3] & 0xFF;
|
// ¼ÆËãÍêÕû°ü³¤¶È£¨°üÍ·+Êý¾Ý+УÑ飩
|
int totalPacketLen = 4 + dataLenField + 2; // Ôö¼Ó2×Ö½ÚУÑéλ
|
|
// ¼ì²éÊÇ·ñÓÐ×ã¹»Êý¾Ý¹¹³ÉÍêÕû°ü
|
if (index + totalPacketLen > bufferLength) {
|
break; // Êý¾Ý²»×㣬µÈ´ý¸ü¶àÊý¾Ý
|
}
|
|
// ÌáÈ¡ÍêÕûÊý¾Ý°ü
|
byte[] packetData = new byte[totalPacketLen];
|
System.arraycopy(buffer, index, packetData, 0, totalPacketLen);
|
|
// Ñé֤УÑéºÍ
|
if (verifyChecksum(packetData)) {
|
// ½âÎöµ¥¸öÊý¾Ý°ü
|
DataPacket packet = parseSinglePacket(packetType, packetData);
|
if (packet != null) {
|
packets.add(packet); // Ìí¼Óµ½½á¹ûÁбí
|
}
|
index += totalPacketLen; // ÒÆ¶¯µ½ÏÂÒ»¸ö°ü
|
} else {
|
index++; // УÑéʧ°Ü£¬Ìø¹ýµ±Ç°×Ö½Ú
|
}
|
} else {
|
index++; // ·Ç°üÍ·±êʶ£¬¼ÌÐø²éÕÒ
|
}
|
}
|
|
// ÇåÀíÒÑ´¦ÀíÊý¾Ý
|
if (index > 0) {
|
int remaining = bufferLength - index;
|
if (remaining > 0) {
|
// ÒÆ¶¯Ê£ÓàÊý¾Ýµ½»º³åÇø¿ªÍ·
|
System.arraycopy(buffer, index, buffer, 0, remaining);
|
}
|
bufferLength = remaining; // ¸üлº³åÇø³¤¶È
|
}
|
|
return packets;
|
}
|
|
// УÑéÊý¾Ý°üÍêÕûÐÔ
|
private boolean verifyChecksum(byte[] packet) {
|
int len = packet.length;
|
if (len < 4) return false; // ³¤¶È²»×ã
|
|
int sum = 0;
|
// ¼ÆËã´ÓµÚ3×Ö½Úµ½µ¹ÊýµÚ3×ֽڵĺͣ¨Ìø¹ý°üÍ·ºÍУÑé룩
|
for (int i = 2; i < len - 2; i++) {
|
sum += packet[i] & 0xFF;
|
}
|
// È¡·´µÃµ½16λУÑéºÍ
|
sum = ~sum & 0xFFFF;
|
|
// ÌáÈ¡°üÖеÄУÑéºÍ£¨Ð¡¶Ë¸ñʽ£©
|
int receivedChecksum = ((packet[len - 1] & 0xFF) << 8) | (packet[len - 2] & 0xFF);
|
|
// ±È½ÏУÑéºÍ
|
return sum == receivedChecksum;
|
}
|
|
// ½âÎöµ¥¸öÊý¾Ý°ü
|
private DataPacket parseSinglePacket(int packetType, byte[] packet) {
|
|
// ´´½¨Êý¾Ý°ü¶ÔÏ󣨰üº¬°üÀàÐÍ£©
|
return new DataPacket(packetType, packet);
|
}
|
|
// Êý¾Ý°üÄÚ²¿Àà
|
public static class DataPacket {
|
private final int packetType; // °üÀàÐÍ
|
private final byte[] packet;//°üÊý¾Ý
|
|
public DataPacket(int packetType, byte[] packet) {
|
this.packetType = packetType;
|
this.packet = packet;
|
}
|
|
// »ñÈ¡°üÀàÐÍ
|
public int getPacketType() {
|
return packetType;
|
}
|
|
// °üÊý¾Ý
|
public byte[] getPacket() {
|
return packet;
|
}
|
|
}
|
|
// HEX×Ö·û´®×ª×Ö½ÚÊý×é
|
public static byte[] hexStringToBytes(String hex) {
|
// ÒÆ³ý¿Õ¸ñ
|
hex = hex.replaceAll("\\s", "");
|
int len = hex.length();
|
// ´´½¨½á¹ûÊý×é
|
byte[] data = new byte[len / 2];
|
// ÿÁ½¸ö×Ö·ûת»»Ò»¸ö×Ö½Ú
|
for (int i = 0; i < len; i += 2) {
|
// ¸ßλת»»
|
int high = Character.digit(hex.charAt(i), 16) << 4;
|
// µÍλת»»
|
int low = Character.digit(hex.charAt(i + 1), 16);
|
data[i / 2] = (byte) (high | low);
|
}
|
return data;
|
}
|
}
|