我正试图在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)
这需要以根用户身份运行,并在端口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 1
、message 3
和message 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的协议应该能够容忍数据包丢失,UDP是否会一直丢弃数据包?即便如此,为什么在本地接口上发送数据包时会丢弃?
将服务器绑定到127.0.0.1
而不是0.0.0.0
具有相同的结果。
用一种愚蠢的方式解决了这个问题;如果有其他方法,请告诉我,我会改变接受的答案。
解决方案只是使用绑定在同一端口上的两个套接字;一个是原始的,一个不是原始的:
这使得“无法到达目的地”ICMP数据包消失,并使所有数据包都能正常通过。我认为操作系统需要一个监听端口的非原始套接字,以便一切顺利进行,然后监听同一端口的任何原始套接字都将接收数据包的副本。
相关问题 更多 >
编程相关推荐