""" Lab002, часть 2. Повреждение одного бита пакета без контроля целостности. Цель: 1. Сформировать цифровой пакет. 2. Намеренно изменить один бит полезной нагрузки. 3. Разобрать повреждённый пакет. 4. Убедиться, что без CRC повреждение не обнаруживается. """ import struct # ============================================================ # Константы протокола # ============================================================ SYNC_WORD = 0xAA55 PROTOCOL_VERSION = 1 MESSAGE_TYPE_TEXT = 1 HEADER_FORMAT = ">HBBHH" # ============================================================ # Формирование исходного пакета # ============================================================ message = "ПРИВЕТ SDR" payload = message.encode("utf-8") sequence_number = 1 message_type = MESSAGE_TYPE_TEXT payload_length = len(payload) header = struct.pack( HEADER_FORMAT, SYNC_WORD, PROTOCOL_VERSION, message_type, sequence_number, payload_length, ) packet = header + payload print("Исходное сообщение:") print(message) print("\nИсходный пакет:") print(packet.hex(" ")) # ============================================================ # Имитация повреждения пакета # ============================================================ # bytes нельзя изменять напрямую. # Поэтому преобразуем пакет в изменяемый массив bytearray. corrupted_packet = bytearray(packet) header_size = struct.calcsize(HEADER_FORMAT) # В строке "ПРИВЕТ SDR": # # "ПРИВЕТ" занимает 12 байтов UTF-8, # пробел занимает 1 байт, # буква S находится по индексу 13 внутри PAYLOAD. payload_byte_index = 13 # Полный индекс внутри пакета: packet_byte_index = header_size + payload_byte_index original_byte = corrupted_packet[packet_byte_index] # XOR с 0x01 изменяет младший бит: # # 0x53 = 01010011 = S # 0x52 = 01010010 = R corrupted_packet[packet_byte_index] ^= 0x01 corrupted_byte = corrupted_packet[packet_byte_index] print("\nИзменяемый байт внутри пакета:") print( f"До повреждения: " f"{original_byte:3d} " f"= 0x{original_byte:02X} " f"= {original_byte:08b}" ) print( f"После повреждения: " f"{corrupted_byte:3d} " f"= 0x{corrupted_byte:02X} " f"= {corrupted_byte:08b}" ) print("\nПовреждённый пакет:") print(bytes(corrupted_packet).hex(" ")) # ============================================================ # Разбор повреждённого пакета # ============================================================ received_header = corrupted_packet[:header_size] received_payload = corrupted_packet[header_size:] ( received_sync, received_version, received_type, received_sequence, received_length, ) = struct.unpack(HEADER_FORMAT, received_header) # ============================================================ # Проверки структуры # ============================================================ assert received_sync == SYNC_WORD assert received_version == PROTOCOL_VERSION assert received_type == MESSAGE_TYPE_TEXT assert received_sequence == sequence_number assert received_length == len(received_payload) print("\nВсе проверки заголовка пройдены.") restored_message = bytes(received_payload).decode("utf-8") print("\nСообщение после повреждения:") print(restored_message) print("\nИсходное сообщение:") print(message) # ============================================================ # Проверка результата эксперимента # ============================================================ assert restored_message != message print("\nПовреждение данных произошло.") print("Но заголовок и длина пакета остались правильными.") print("Без CRC приёмник не смог определить ошибку.")