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 parsePackets() { List 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; } }