""" Lab003. Обнаружение повреждения пакета с помощью CRC-32. Цель: 1. Сформировать пакет с CRC-32. 2. Проверить исправный пакет. 3. Изменить один бит полезной нагрузки. 4. Убедиться, что CRC обнаруживает повреждение. """ import struct import zlib # ============================================================ # Константы протокола # ============================================================ SYNC_WORD = 0xAA55 PROTOCOL_VERSION = 1 MESSAGE_TYPE_TEXT = 1 HEADER_FORMAT = ">HBBHH" CRC_FORMAT = ">I" CRC_SIZE = struct.calcsize(CRC_FORMAT) # ============================================================ # Формирование исходного пакета # ============================================================ message = "ПРИВЕТ SDR" payload = message.encode("utf-8") sequence_number = 1 payload_length = len(payload) header = struct.pack( HEADER_FORMAT, SYNC_WORD, PROTOCOL_VERSION, MESSAGE_TYPE_TEXT, sequence_number, payload_length, ) # CRC вычисляется по заголовку и полезной нагрузке. packet_without_crc = header + payload crc_value = zlib.crc32(packet_without_crc) & 0xFFFFFFFF crc_bytes = struct.pack( CRC_FORMAT, crc_value, ) packet = packet_without_crc + crc_bytes print("Исходное сообщение:") print(message) print("\nCRC-32 исходного пакета:") print(f"0x{crc_value:08X}") print("\nПолный пакет:") print(packet.hex(" ")) print("\nДлина полного пакета:") print(len(packet), "байт") # ============================================================ # Проверка исправного пакета # ============================================================ received_data = packet[:-CRC_SIZE] received_crc_bytes = packet[-CRC_SIZE:] (received_crc,) = struct.unpack( CRC_FORMAT, received_crc_bytes, ) calculated_crc = zlib.crc32(received_data) & 0xFFFFFFFF print("\n--- Проверка исправного пакета ---") print(f"CRC из пакета: 0x{received_crc:08X}") print(f"CRC вычисленный: 0x{calculated_crc:08X}") assert received_crc == calculated_crc print("Результат: пакет не повреждён.") # ============================================================ # Имитация повреждения одного бита # ============================================================ corrupted_packet = bytearray(packet) header_size = struct.calcsize(HEADER_FORMAT) # Буква S находится по индексу 13 внутри PAYLOAD. payload_byte_index = 13 packet_byte_index = header_size + payload_byte_index original_byte = corrupted_packet[packet_byte_index] # Меняем младший бит: # S = 0x53 # R = 0x52 corrupted_packet[packet_byte_index] ^= 0x01 corrupted_byte = corrupted_packet[packet_byte_index] print("\n--- Повреждение одного бита ---") print( f"До повреждения: " f"0x{original_byte:02X} = {original_byte:08b}" ) print( f"После повреждения: " f"0x{corrupted_byte:02X} = {corrupted_byte:08b}" ) # ============================================================ # Проверка повреждённого пакета # ============================================================ corrupted_data = bytes( corrupted_packet[:-CRC_SIZE] ) corrupted_crc_bytes = bytes( corrupted_packet[-CRC_SIZE:] ) (received_crc_after_corruption,) = struct.unpack( CRC_FORMAT, corrupted_crc_bytes, ) calculated_crc_after_corruption = ( zlib.crc32(corrupted_data) & 0xFFFFFFFF ) print("\n--- Проверка повреждённого пакета ---") print( f"CRC из пакета: " f"0x{received_crc_after_corruption:08X}" ) print( f"CRC вычисленный: " f"0x{calculated_crc_after_corruption:08X}" ) if received_crc_after_corruption != calculated_crc_after_corruption: print("\nРезультат: CRC обнаружил повреждение пакета.") else: print("\nРезультат: повреждение не обнаружено.") # ============================================================ # Показываем повреждённое сообщение # ============================================================ corrupted_payload = corrupted_data[header_size:] corrupted_message = corrupted_payload.decode("utf-8") print("\nСообщение внутри повреждённого пакета:") print(corrupted_message) # ============================================================ # Автоматические проверки # ============================================================ assert corrupted_message == "ПРИВЕТ RDR" assert ( received_crc_after_corruption != calculated_crc_after_corruption ) print("\nПроверка пройдена: CRC-32 обнаружил изменение одного бита.")