【问题标题】:Python raw socket listening for UDP packets; only half of the packets received侦听 UDP 数据包的 Python 原始套接字;只收到一半的数据包
【发布时间】:2012-04-15 16:33:49
【问题描述】:

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

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')

始终,只有第一条、第三条和第五条消息(message 1message 3message 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 持续丢弃数据包的预期行为,因为使用它的协议应该能够容忍数据包丢失?即便如此,为什么在本地接口上发送的数据包会被丢弃?

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

【问题讨论】:

  • 消息堆栈有时会发生奇怪的事情。在这种情况下,以太网适配器使用环回,但是,数据包“物理上”仍然在卡上,然后由驱动程序解释如何对消息队列进行排序。只是一些研究点可以提供帮助。
  • @Etienne, FlavorScape 我每隔一个数据包都会收到错误,这似乎太规律了,不可能是网络错误...
  • 是的,每两个数据包发生一次,这意味着如果您发送2*n 数据包,所有2*i+1 形式的数据包都将无法通过。我不认为这可能是丢包,因为这都是在本地接口上。
  • 我怀疑这是因为您使用的是 RAW DGRAM 或类似的东西。
  • 已确认。如果您使用socket.SOCK_DGRAM 服务器端,它会按预期工作。

标签: python sockets networking udp packet-capture


【解决方案1】:

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

解决方法就是使用绑定在同一个端口上的两个套接字;一份生的,一份不生的:

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 数据包消失,并使所有数据包正常通过。我认为操作系统希望在端口上监听一个非原始套接字以使事情顺利进行,然后在同一端口上监听的任何原始套接字都将接收数据包的副本。

【讨论】:

  • 很有趣,知道这一点真的很高兴!
  • 这正是我想要的! (但是对于需要稍微不同的 RAW 套接字初始化的 Windows)
猜你喜欢
  • 2014-08-22
  • 2011-05-10
  • 2017-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
  • 2021-08-17
相关资源
最近更新 更多