我的结论对使用socket接收多播的代码是否合理?

2024-04-16 14:26:28 发布

您现在位置:Python中文网/ 问答频道 /正文

基于堆栈中的MC接收器: How do you UDP multicast in Python?

我想完全理解发生了什么。以下是我理解的和不理解的:

据我所知:socket_name = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)=>;正在创建IP协议版本为4的套接字,该套接字将使用UDP接收MC数据报

socket_name.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)这负责设置套接字可以使用相同地址的参数

(在本例中是port,因为对于多播,SO\u REUSEADDR=SO\u REUSEPORT)。 (段落多播~ How do SO_REUSEADDR and SO_REUSEPORT differ?

如果IS_ALL_GROUPS: socket_name.bind(('', MCAST_PORT))表示如果IS_ALL_GROUPS为真,则将套接字绑定到任何地址,否则:socket_name.bind((MCAST_GRP, MCAST_PORT))表示将套接字绑定到特定的IP地址

mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)表示将IP地址转换为二进制形式,socket_name.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)表示我们添加组成员,在这行数据包开始到达之后

但是有些事情我不明白

为什么当我使用IS_ALL_GROUPS = trueMCAST_GRP = '239.0.1.104'程序可以启动,当参数为false时,它没有绑定到特定的多播地址?我的逻辑是,当参数为true时,它绑定到他从IGMP join消息获得的任何MCast addres;当参数为false时,它绑定到特定的给定地址。我说的对吗

我有多线程程序,分析比特率,我提供了一个以上的列表形式的地址。当我将IS_ALL_GROUPS设置为false时,程序可以正确地打印出来,例如10.5, 4.5, 5.0,其中每个结果是来自唯一地址的一个流的比特率,但是所有地址共享相同的端口12345。当我将IS_ALL_GROUPS设为true时,程序对结果进行汇总,得出20.0, 20.0, 20.0,您知道原因是什么吗

import socket
import struct

MCAST_GRP = '239.0.1.104'
MCAST_PORT = 12345
IS_ALL_GROUPS = True

socket_name = 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
    socket_name.bind(('', MCAST_PORT))
else:
    # on this port, listen ONLY to MCAST_GRP
    socket_name.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:
  print socket_name.recv(10240)

Tags: nameipsoisport地址socketall
1条回答
网友
1楼 · 发布于 2024-04-16 14:26:28

我认为发生了一些事情:

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

应该probably be

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

IPv4中唯一基于“数据报”的协议是UDP,protocol字段仅用于tcpdump等程序使用的“原始套接字”。但这不重要

下一步:

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

只允许多个套接字同时绑定到同一个(addr, port)组合,即您可以一次或连续快速运行程序的多个副本。我想你是这么说的

下一步:

sock.bind((host, port))

表示要接收指定地址和端口的数据包。特殊地址''(即INADDR_ANY)意味着内核不应该对地址进行任何过滤。在这个阶段,您可能不想绑定到任何特定的地址,请参见What does it mean to bind a multicast (UDP) socket?

下一步:

mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

我建议对格式字符串使用"=4sl",因为这样可以得到8个字节,而不是16个字节,并且与我(Linux)系统上的C^{}一致。这种填充差异可能只是32/64位的问题,而且似乎没有什么坏处

总结:1.setsockopt(IP_ADD_MEMBERSHIP)调用要求内核的网络堆栈(通过IGMP)安排发送到MCAST_GRP的多播数据包,以传送到连接到主机的网络接口。2.bind()调用已安排通过网络接口接收的数据包,以使其进入进程中的套接字。重要的是,bind()指定INADDR_ANY,以便所有到达的多播数据包都被传递到进程中,而不是被过滤

可能有用的命令行有:

tcpdump -i eth0 -vv 'ip proto 2'

它转储IGMP数据包,并且:

tcpdump -i eth0 -vv 'net 224.0.0.0/4'

哪个转储多播数据包

我不知道你的“多线程分析程序”在做什么,因为你没有给出任何相关的信息。你发布的代码也错了,大概socket_namesock是一样的吧?我还建议使用python3,因为python2正在消亡

相关问题 更多 >