为什么pythonsocket.recvfrom得到的字节流和WireShark抓取的不一样?
Why the bytes stream got by python socket.recvfrom is different from that crawled by WireShark?
我使用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)
字节0x3F
是ASCII'?'
字符。这通常意味着数据被视为文本并且正在通过不支持正在转换的字节的字符集转换。
请注意,0x3F
仅替换大于 0x7F
的字节(ASCII 支持的最后一个字节)。 0x80-0xFF
范围内的非 ASCII 字节受字符集解释的约束。
这是有道理的,因为您正在使用 returns 和 string
的 recvfrom()
版本,因此接收到的字节需要转换为 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
字节数。
我使用python套接字发送一个DNS查询数据包套接字并监听响应。最后,我如预期的那样通过 socket.recvfrom(2048)
函数得到了一个 DNS 响应数据包。但奇怪的是,我把响应包和Wireshark抓取的包对比了一下,发现还是有很多不同。
在第二张图片中会发现差异为 3f
。
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)
字节0x3F
是ASCII'?'
字符。这通常意味着数据被视为文本并且正在通过不支持正在转换的字节的字符集转换。
请注意,0x3F
仅替换大于 0x7F
的字节(ASCII 支持的最后一个字节)。 0x80-0xFF
范围内的非 ASCII 字节受字符集解释的约束。
这是有道理的,因为您正在使用 returns 和 string
的 recvfrom()
版本,因此接收到的字节需要转换为 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
字节数。