Почему поток байтов, полученный python socket.recvfrom, отличается от того, который просматривал WireShark? - PullRequest
0 голосов
/ 12 сентября 2018

Я использовал сокет python для отправки сокета пакета DNS-запроса и прослушивания ответа. Наконец, я получил ответный пакет DNS с помощью функции socket.recvfrom(2048), как и ожидалось. Но как ни странно, когда я сравнил ответный пакет с пакетом, отсканированным Wireshark, я обнаружил, что существует много различий.

Различия будут найдены как 3f на втором изображении.

Пакет ответов DNS (выделенная часть), отсканированный Wireshark

Пакет ответа DNS, полученный socket.recvfrom(2048)

Создание кодов деталей гнезда:

    ipv = check_ip(dst)
    udp = socket.getprotobyname(Proto.UDP)
    if ipv == IPV.ERROR:
        return None
    elif ipv == IPV.IPV4:
        return socket.socket(socket.AF_INET, socket.SOCK_DGRAM, udp)
    elif ipv == IPV.IPV6:
        return socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, udp)
    else:
        return None

Коды получения пакета ответа DNS:

    remained_time = 0
    while True:
        remained_time = self.timeout - timeit.default_timer() + sent_time
        readable = select.select([sock], [], [], remained_time)[0]
        if len(readable) == 0:
            return (-1, None)

        packet, addr = sock.recvfrom(4096)

1 Ответ

0 голосов
/ 12 сентября 2018

Байт 0x3F является символом ASCII '?'. Обычно это означает, что данные обрабатываются как текст и проходят преобразование кодировки, которое не поддерживает преобразование байтов.

Обратите внимание, что 0x3F заменяет только байты, которые> 0x7F (последний байт, поддерживаемый ASCII). Не-ASCII байты в диапазоне 0x80-0xFF подлежат интерпретации кодировки.

Это имеет смысл, поскольку вы используете версию recvfrom(), которая возвращает string, поэтому полученные байты необходимо преобразовать в кодировку Python по умолчанию string.

Так как вместо этого вам нужны необработанные байты, используйте recvfrom_into() для заполнения заранее выделенного bytearray, например:

packet = bytearray(4096)
remained_time = 0
while True:
    remained_time = self.timeout - timeit.default_timer() + sent_time
    readable = select.select([sock], [], [], remained_time)[0]
    if len(readable) == 0:
        return (-1, None)
    nbytes, addr = sock.recvfrom_into(packet)

Затем вы можете использовать packet до nbytes количества байтов по мере необходимости.

...