python怎么接收udp报文_在Linux上使用python接收多播UDP数据报

本文描述了作者在Linux上用Python接收多播UDP数据时遇到的问题,即代码在Windows上正常工作但在Linux上无法接收到数据。经过排查,问题在于接口未加入多播地址。解决方案是确保接口拥有与数据包相同网络段的IP,并在IP_ADD_MEMBERSHIP调用中使用该IP,而不是使用INADDR_ANY。在某些情况下,可能仅需要完成第一步。

I have a hardware device that sends multicast data on my network. I have written a python script that receives the data and prints it. However, I've found that it only works on my Windows XP PC and doesn't work on my Ubuntu Linux 10.04 PC. Under Linux, nothing is received. It just goes round the while loop and there's never any data received. My code is posted below. Can you see any reason why this will not work under Linux? Thanks, Rab.

# Multicast client

# Adapted from: http://chaos.weblogs.us/archives/164

# on 05/03/2013

import socket

ANY = "0.0.0.0"

MCAST_ADDR = "224.0.33.154"

MCAST_PORT = 31800

# Create a UDP socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)

# Allow multiple sockets to use the same PORT number

sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

# Bind to the port that we know will receive multicast data

sock.bind((ANY,MCAST_PORT))

# Tell the kernel that we are a multicast socket

sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)

# Tell the kernel that we want to add ourselves to a multicast group

# The address for the multicast group is the third param

status = sock.setsockopt(socket.IPPROTO_IP,

socket.IP_ADD_MEMBERSHIP,

socket.inet_aton(MCAST_ADDR) + socket.inet_aton(ANY));

# setblocking(0) is equiv to settimeout(0.0) which means we poll the socket.

# But this will raise an error if recv() or send() can't immediately find or send data.

sock.setblocking(0)

while 1:

try:

data, addr = sock.recvfrom(1024)

except socket.error as e:

pass

else:

print "From: ", addr

print "Data: ", data

Here's some sample output from my Windows PC:

From: ('0.0.0.0', 31801)

Data: EDCP

Note the remote hardware device does not have an IP address and is using address 0.0.0.0

EDIT: I've now found that this also doesn't work on my Windows laptop. So, it doesn't look like it's specific to the OS. Furthermore, I've tried running another script to send multicast data to the same multicast address and port. I can send from one PC and all the others are able to receive correctly using my receive script. But, only my one Windows PC is able to receive the data from the hardware device in question. I'm wondering if it is something to do with the ethernet adapters or their configuration. Could it be something to do with the fact that the harware device has IP address 0.0.0.0 and that these ethernet adapters and/or my receiver script needs told to receive messages with this address? Running Wireshark on the Linux PCs sees the data from the hardware device.

解决方案

I fought this same issue for two days. Wireshark saw the packets but my code did not. None of the supposedly "definitive" answers from various sources worked for me. The key came from https://serverfault.com/questions/163244/linux-kernel-not-passing-through-multicast-udp-packets.

Running "ip maddr" showed that code similar to yours was not adding the multicast address to any interface. I forced it to be added with smcroute (see link above). Still no joy. The packets have a source IP of 172.22... My interface is 172.17... I added a 172.22 address to that NIC. Bingo! Now my code received the packets.

Now how to make the program work without smcroute? I commented out the setsockopt() calls. Still worked. Unlinked the multicast address with smcroute -- failed. Uncommented the setsockopt() calls and replaced "ANY" with my 172.22 address. Success!

Summary:

Make sure you have an IP on the same network segment as the incoming packets.

Use that address in the IP_ADD_MEMBERSHIP call instead of INADDR_ANY.

It's possible you won't need to do 2) if you only have one NIC. I have three and must do it.

In case it's germane, I'm using Ubuntu 12.04. I did not need to change any of the default /etc/sysctl.conf settings as others have described. I tried them. They did not help, so I reset them back to installation defaults.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值