gpt4 book ai didi

Python 原始套接字监听 UDP 数据包;只收到一半的数据包

转载 作者:太空狗 更新时间:2023-10-29 21:38:00 25 4
gpt4 key购买 nike

我正在尝试在 Python 中创建一个仅监听 UDP 数据包的原始套接字:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
s.bind(('0.0.0.0', 1337))
while True:
print s.recvfrom(65535)

这需要以 root 身份运行,并在端口 1337 上创建一个原始套接字,它会监听 UDP 数据包并在收到时打印它们;没有问题。

现在让我们做一个小客户端来测试这是否有效:

import socket
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.connect(('127.0.0.1', 1337))
c.send('message 1')
c.send('message 2')
c.send('message 3')
c.send('message 4')
c.send('message 5')
c.send('message 6')

一致地,只有第一条、第三条和第五条消息(消息 1消息 3消息 5)会通过并被发送打印在服务器输出中。第二条、第四条和第六条消息没有出现在服务器输出中,而是客户端得到一个异常:

>>> c.send('message 2')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
socket.error: [Errno 111] Connection refused

在 Wireshark 中运行它表明它正在收到“无法到达目标”的 ICMP 回复。我已经能够在 3 台不同的机器上重现它(虽然都运行 Linux)。我错过了什么吗?这是 UDP 持续丢弃数据包的预期行为吗,因为使用它的协议(protocol)应该容忍数据包丢失?即便如此,为什么在本地接口(interface)上发送数据包时会被丢弃?

将服务器绑定(bind)到 127.0.0.1 而不是 0.0.0.0 具有相同的结果。

最佳答案

以一种愚蠢的方式解决了它;如果有其他方法,请告诉我,我会更改已接受的答案。

解决方案就是使用绑定(bind)在同一个端口上的两个套接字;一种是生的,一种不是生的:

import socket, select
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.bind(('0.0.0.0', 1337))
s2 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
s2.bind(('0.0.0.0', 1337))
while True:
r, w, x = select.select([s1, s2], [], [])
for i in r:
print i, i.recvfrom(131072)

这会使“目标无法到达”的 ICMP 数据包消失,并使所有数据包都正常通过。我认为操作系统希望非原始套接字在端口上监听以便一切顺利,然后在同一端口上监听的任何原始套接字都会收到数据包的副本。

关于Python 原始套接字监听 UDP 数据包;只收到一半的数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9969259/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com