【发布时间】:2022-03-30 07:39:53
【问题描述】:
我正在尝试测试一个 UDP 程序,如果它接收到带有错误 UDP 校验和的数据会发生什么。奇怪的是,它似乎没有任何效果,并且成功接收了有效载荷,至少在 OS X 上通过 loopback 接口。
下面是一个示例,其中数据使用SOCK_RAW + IPPROTO_UDP 发送,手动将校验和指定为不正确的内容,并使用SOCK_DGRAM 接收。
import asyncio
import socket
import struct
async def server():
with \
socket.socket(
socket.AF_INET, socket.SOCK_DGRAM
) as sock:
sock.setblocking(False)
sock.bind(('', 4567))
payload = await loop.sock_recv(sock, 512)
print(payload) # Prints b'somedata'
async def main():
asyncio.ensure_future(server())
await asyncio.sleep(0)
with socket.socket(
family=socket.AF_INET, type=socket.SOCK_RAW, proto=socket.IPPROTO_UDP,
) as sock:
local_ip = '127.0.0.1'
src_port = 4566
dest_port = 4567
payload = b'somedata'
length = 8 + len(payload)
checksum = 3 # 3 is not the right checksum
header_bad_checksum = struct.pack('!4H', src_port, dest_port, length, checksum)
sock.sendto(header_bad_checksum + payload, (local_ip, 4567))
await asyncio.sleep(1)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
这是为什么?我本来希望有效载荷被忽略。
此 UDP 消息的 Wireshark 转储如下,显示(在这种情况下)校验和为 3。
【问题讨论】:
-
据我所知,
sendto()只是发送字节;它不关心校验和验证。您是否有其他说明的文档链接? -
@JohnGordon 好吧,不。而且,我希望接收端进行验证,而不是发送,因为我认为校验和的目的是捕获传输过程中引入的错误。
-
您是否检查过您收到的校验和是否与您发送的校验和相同?这可能是由校验和卸载引起的。您的 NIC 可能会用正确的 NIC 覆盖校验和计算。
-
@HugoSadok 我现在包含了来自 Wireshark 的屏幕截图,我认为它表明它是相同的。
-
@HugoSadok 经过一些初步测试后,根据 Wireshark 接收到来自我网络上另一台计算机的校验和错误的 UDP 数据包,但随后 Python 中的套接字似乎没有接收到它们。所以它确实表明 macOS 在环回接口中忽略了它们。这有点烦人,因为我希望将环回接口用作测试的“真实”接口,但在这方面它的行为似乎有所不同。
标签: python python-3.x sockets udp python-asyncio