为什么python socket.recvfrom获得的字节流与WireShark检索的字节流不同?

时间:2018-09-12 05:52:05

标签: python sockets recvfrom

我使用python套接字发送DNS查询数据包套接字并监听响应。最终,我按预期通过socket.recvfrom(2048)函数获得了DNS响应数据包。但是奇怪的是,当我将响应数据包与Wireshark爬网的数据包进行比较时,发现存在很多差异。

差异将在第二张图片中显示为3f

Wireshark爬行的DNS响应数据包(突出显示的部分)

socket.recvfrom(2048)

获得的DNS响应数据包

创建套接字部件代码:

    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 :(得分:1)

字节0x3F是ASCII '?'字符。通常,这意味着数据被视为文本,并且正在通过不支持要转换的字节的字符集转换。

请注意,0x3F仅替换> 0x7F(ASCII支持的最后一个字节)的字节。 0x80-0xFF范围内的非ASCII字节受字符集解释。

这很有意义,因为您正在使用返回recvfrom()的{​​{1}}版本,因此需要将接收到的字节转换为Python的默认string编码。

因为您需要原始字节,所以使用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个字节。