【问题标题】:How to change a socket's IP_MULTICAST_IF如何更改套接字的 IP_MULTICAST_IF
【发布时间】:2012-07-27 20:35:07
【问题描述】:

我有一台具有 5 个接口的计算机:3 个具有公共 IP 和 2 个本地 IP。我正在尝试向 UDP 服务器发送“HELLO”,但我想将接口更改为本地 IP 地址之一。我做了一些研究,这是我需要在 python 中添加的行:

sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton("64.195.10.11"))

64.195.10.11 是我要更改的 IP

所以我的python代码是这样的:

import socket

MCAST_GRP = '224.0.0.1'
MCAST_PORT = 10222

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton("64.195.10.10"))
sock.sendto("HELLO", (MCAST_GRP, MCAST_PORT))

当我在我的 3 个公共 IP 地址之间进行更改时,它可以完美运行。但是,如果我在参数中输入本地 IP,它就不起作用(数据包未传递)。我不确定是脚本没有发送,还是服务器没有接收。发生了什么?

止损

编辑:我正在使用两种方式收听:

import socket
import sys

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", 10222))
sock.setsockopt(socket.IPPROTO_IP,
                                 socket.IP_ADD_MEMBERSHIP,
                                 socket.inet_aton("224.0.0.1") +
                                 socket.inet_aton("64.195.10.11"))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0)

while True:
    print >>sys.stderr, '\nwaiting to receive message'
    data, address = sock.recvfrom(1024)

    print >>sys.stderr, 'received %s bytes from %s' % (len(data), address)
    print >>sys.stderr, data

    print >>sys.stderr, 'sending acknowledgement to', address
    sock.sendto('ack', address)

并使用扭曲:

from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
from twisted.application.internet import MulticastServer

class MulticastServerUDP(DatagramProtocol):
    def __init__ (self, group, name):
        self.group = group
        self.name = name
    def startProtocol(self):
        print '%s Started Listening' % self.group
        self.transport.joinGroup(self.group)

    def datagramReceived(self, datagram, address):
        print "%s Received:"%self.name + repr(datagram) + repr(address)

reactor.listenMulticast(10222, MulticastServerUDP('224.0.0.1', 'SERVER1'), listenMultiple = True)             
reactor.run()

【问题讨论】:

  • “它不起作用”不是一个很有帮助的问题描述。 setsockopt 是成功还是失败? sendto 是成功还是失败?
  • @SquallLeohart : 你要测试的服务器和本地地址(私有地址)在同一台机器上?
  • 当我使用RFC 1918 地址时,这段代码完全没有问题; wireshark 显示多播数据包没有问题
  • 所以让我们明确一点,您想将多播从 64.194.10.11 的单播地址发送到 RFC 1918 地址吗?如果不是,请明确指出发送方和接收方的单播地址,因为您的问题很可能比 Python 更基本
  • 如果您的发送方和接收方之间有防火墙,那么您很可能遇到了防火墙问题......它们往往会导致多播配置出现问题

标签: sockets interface ip multicast


【解决方案1】:

如果服务器和客户端在同一台机器上(用于测试),可能需要像这样设置IP_MULTICAST_LOOP 选项(c 代码):

int loop_on = 1;
setsockopt(socket, IPPROTO_IP, IP_MULTICAST_LOOP, &loop_on, sizeof(loop_on));

在python中你可以尝试这样的事情:

sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)

希望对您有所帮助。

编辑:添加一些跟踪(来自我的 Linux 机器)

我使用的代码与 SquallLeohart 发布的代码相同:

#! /usr/bin/python

import socket

MCAST_GRP = '224.0.0.1'
MCAST_PORT = 10222

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton("192.168.1.7"))
sock.sendto("HELLO", (MCAST_GRP, MCAST_PORT))

还有:

#! /usr/bin/python
import socket
import sys

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", 10222))
sock.setsockopt(socket.IPPROTO_IP,
                                 socket.IP_ADD_MEMBERSHIP,
                                 socket.inet_aton("224.0.0.1") +
                                 socket.inet_aton("192.168.1.7"))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0)

while True:
    print >>sys.stderr, '\nwaiting to receive message'
    data, address = sock.recvfrom(1024)

    print >>sys.stderr, 'received %s bytes from %s' % (len(data), address)
    print >>sys.stderr, data

    print >>sys.stderr, 'sending acknowledgement to', address
    sock.sendto('ack', address)

我得到了这个输出:

waiting to receive message
received 5 bytes from ('192.168.1.7', 43761)
HELLO
sending acknowledgement to ('192.168.1.7', 43761)

waiting to receive message
received 5 bytes from ('192.168.1.7', 52326)
HELLO
sending acknowledgement to ('192.168.1.7', 52326)

waiting to receive message

还有 tcpdump:

21:01:33.814728 IP localhost.localdomain.34956 > all-systems.mcast.net.10222: UDP, length 5
21:01:35.364605 IP localhost.localdomain.39078 > all-systems.mcast.net.10222: UDP, length 5
21:01:36.228477 IP localhost.localdomain.49926 > all-systems.mcast.net.10222: UDP, length 5

问候。

【讨论】:

  • 不幸的是,它没有帮助。类似IP地址的接口我切换好像没有问题,比如64.195.10.110, 64.195.10.11, 64.195.10.12 但是比如192.168.1.75就是我不能切换的地址。
  • @SquallLeohart: 你能用 tcpdump 在这里转储一些数据包吗?
  • @SquallLeohart :是的,我发布了它,我在 (192.168.1.7) 上的本地 LAN 上使用它
  • 您关于循环的行没有帮助,因为无论我在同一台机器或两台不同的机器上运行代码,它都会给我同样的问题。我刚刚发现问题是由于我的防火墙设置造成的。我的代码现在可以工作了。无论如何,非常感谢!
【解决方案2】:

答案:我的防火墙不接受来自那个 RFC1918 IP 地址的 udp 数据包。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    • 2020-01-26
    • 2013-07-05
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多