import socket
import struct
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
IS_ALL_GROUPS = True
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if IS_ALL_GROUPS:
# on this port, receives ALL multicast groups
sock.bind(('', MCAST_PORT))
else:
# on this port, listen ONLY to MCAST_GRP
sock.bind((MCAST_GRP, MCAST_PORT))
mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
# For Python 3, change next line to "print(sock.recv(10240))"
print sock.recv(10240)
发送
import socket
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
# regarding socket.IP_MULTICAST_TTL
# ---------------------------------
# for all packets sent, after two hops on the network the packet will not
# be re-sent/broadcast (see https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html)
MULTICAST_TTL = 2
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, MULTICAST_TTL)
# For Python 3, change next line to 'sock.sendto(b"robot", ...' to avoid the
# "bytes-like object is required" msg (https://stackoverflow.com/a/42612820)
sock.sendto("robot", (MCAST_GRP, MCAST_PORT))
import socket
import struct
import argparse
def run(groups, port, iface=None, bind_group=None):
# generally speaking you want to bind to one of the groups you joined in
# this script,
# but it is also possible to bind to group which is added by some other
# programs (like another python program instance of this)
# assert bind_group in groups + [None], \
# 'bind group not in groups to join'
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
# allow reuse of socket (to allow another instance of python running this
# script binding to the same ip/port)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('' if bind_group is None else bind_group, port))
for group in groups:
mreq = struct.pack(
'4sl' if iface is None else '4s4s',
socket.inet_aton(group),
socket.INADDR_ANY if iface is None else socket.inet_aton(iface))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
print(sock.recv(10240))
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--port', type=int, default=19900)
parser.add_argument('--join-mcast-groups', default=[], nargs='*',
help='multicast groups (ip addrs) to listen to join')
parser.add_argument(
'--iface', default=None,
help='local interface to use for listening to multicast data; '
'if unspecified, any interface would be chosen')
parser.add_argument(
'--bind-group', default=None,
help='multicast groups (ip addrs) to bind to for the udp socket; '
'should be one of the multicast groups joined globally '
'(not necessarily joined in this python program) '
'in the interface specified by --iface. '
'If unspecified, bind to 0.0.0.0 '
'(all addresses (all multicast addresses) of that interface)')
args = parser.parse_args()
run(args.join_mcast_groups, args.port, args.iface, args.bind_group)
>>>> from gumd import GumD
>>>> gumd =GumD('235.35.3.5:3535',1)
>>>> gumd.mcast("/home/a/stuff.txt")
# Can also use http(s), UDP and multicast
stream uri: udp://@235.35.3.5:3535
>>>>
使用gumc(客户端)
>>>> from gumc import GumC
>>>> gumc = GumC("udp://@235.35.3.5:3535")
>>>> data = gumc.read(8)
>>>> data
b'Helloooo'
9条答案
按热度按时间wlzqhblo1#
这对我很有效:
接收
发送
它是基于http://wiki.python.org/moin/UdpCommunication中不起作用的示例。
我的系统是... Linux 2.6.31-15-通用#50-Ubuntu SMP星期二11月10日14:54:29 UTC 2009 i686 GNU/Linux Python 2.6.4
eivgtgni2#
向多播组广播的多播发送方:
从多播组读取并将十六进制数据打印到控制台的多播接收器:
i34xakig3#
更好地使用:
而不是:
因为,如果你想在同一个端口上监听多个组播组,你将在所有监听器上得到所有消息。
lmyy7pcs4#
为了加入多播组,Python使用原生操作系统套接字接口。由于Python环境的可移植性和稳定性,许多套接字选项直接转发到原生套接字setsockopt调用。多播操作模式,如加入和删除组成员资格,只能通过
setsockopt
完成。用于接收多播IP分组的基本程序可以看起来像:
它首先创建套接字,绑定套接字,然后通过
setsockopt
触发器触发组播组加入,最后永远接收数据包。发送多播IP帧是直接的。如果您的系统中只有一个NIC,发送此类数据包与发送通常的UDP帧没有什么不同。所有您需要注意的只是在
sendto()
方法中设置正确的目标IP地址。我注意到很多关于互联网的例子实际上是偶然的。甚至在官方的python文档中。所有这些例子的问题都是错误地使用struct.pack。请注意,典型的例子使用
4sl
作为格式,它与实际的操作系统套接字接口结构不一致。我将尝试描述在对python套接字对象执行setsockopt调用时,在底层发生了什么。
Python将setsockopt方法调用转发到原生C套接字接口。Linux套接字文档(参见
man 7 ip
)为IP_ADD_MEMBERSHIP选项介绍了ip_mreqn
结构的两种形式。最短的形式是8字节长,最长的是12字节长。上面的例子生成了8字节setsockopt
调用,其中前四个字节定义multicast_group
,后四个字节定义interface_ip
。sirbozc55#
只是另一个答案来解释其他答案的代码中的一些微妙之处:
socket.INADDR_ANY
-(编辑)在IP_ADD_MEMBERSHIP
的上下文中,这并没有真正将套接字绑定到所有接口,而只是选择多播启动的默认接口(根据路由表)参阅What does it mean to bind a multicast (UDP) socket?了解更多关于多播如何工作的信息
组播接收方:
样品使用:(在两个控制台中运行下面的命令,并选择您自己的--iface(必须与接收多播数据的接口相同))
python3 multicast_recv.py --iface='192.168.56.102' --join-mcast-groups '224.1.1.1' '224.1.1.2' '224.1.1.3' --bind-group '224.1.1.2'
python3 multicast_recv.py --iface='192.168.56.102' --join-mcast-groups '224.1.1.4'
多播发送方:
样品使用:#假设接收方绑定到下面的组播组地址,某个程序请求加入该组播组,为简化情况,假设接收方和发送方在同一个子网下
python3 multicast_send.py --mcast-group '224.1.1.2'
python3 multicast_send.py --mcast-group '224.1.1.4'
yyyllmsg6#
看看py-multicast,网络模块可以检查接口是否支持多播(至少在Linux上)。
可能是由于接口不支持多播而导致无法看到IGMP的问题?
wvt8vs2t7#
要使客户端代码(来自tolomea)在Solaris上工作,需要将
IP_MULTICAST_TTL
套接字选项的ttl值作为unsigned char传递,否则会得到一个错误,我在Solaris 10和11上是这样做的:qqrboqgw8#
牙龈D和牙龈C https://github.com/futzu/gumd
我使用GumD主要是视频,但你可以使用任何类型的文件。
gumd(后台进程)
使用gumc(客户端)
roqulrg39#
Tolomea的回答对我有用我黑进了套接字服务器UDPServer也是