Search code examples
pythontwistedmulticast

Twisted Python: multicast server not working as expected


I am experimenting with twisted python's multicast protocol. This is a simple example:

I created two servers, listening on 224.0.0.1 and 224.0.0.2 like below:

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
        # Join a specific multicast group, which is the IP we will respond to
        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.listenMulticast(10222, MulticastServerUDP('224.0.0.1', 'SERVER2'), listenMultiple = True)

reactor.run()

Then I run this code to send "HELLO":

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.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
sock.sendto("HELLO", (MCAST_GRP, MCAST_PORT))

The results were quite confusing. There are several cases:

-When I set all group IP and MCAST_GRP to 224.0.0.1, both servers received the message (expected) -When I set both servers' group IP to 224.0.0.1 and MCAST_GRP in the sending script to 224.0.0.2 (or something different from 224.0.0.1), both servers did not receive the message (expected)

-When I set one server's group IP to 224.0.0.1 and the other 224.0.0.2, strange things happen. When I set MCAST_GRP to 224.0.0.1 or 224.0.0.2, I expected only ONE of the two servers to receive the message. The result was that BOTH servers received the message. I am not sure what is going on. Can someone explain this?

Note: I am running these on the same machine.

SL


Solution

  • Multicast is wacky and platform (Linux, Windows, OS X, etc) implementations of multicast are even wackier.

    Twisted is just reflecting the platform's multicast behavior here, so this is only vaguely a Twisted-related question. Really, it's a multicast question and a platform question.

    Here's a slightly educated guess as to what's going on.

    Multicast works by having hosts subscribe to addresses. When a program running on the host joins a group (eg 224.0.0.1), the host makes a note of this locally and does some network operations (IGMP) to tell nearby hosts (probably via a router, but I'm fuzzy on the details of this part) that it is now interested in messages for that group.

    In the ideal universe of the creators of multicast, that subscription propagates all the way through the internet. This is necessary so that whenever anyone anywhere on the internet sends a message to that group, whichever routers get their hands on it can deliver it to all the hosts that have subscribed to the group. This is supposed to be more efficient than broadcast because only hosts that have subscribed need the message delivered to them. Since routers are tracking subscriptions, they can skip sending the traffic down links that have no subscribed hosts.

    In the real universe, multicast subscriptions usually don't get propagated very far (eg, they reach the first router, probably the one running your house LAN, and stop there).

    So it may seem like all that information about the ideal universe is irrelevant to this scenario. However! My suspicion is that most of the people implementing multicast thought really, really hard about that first part and were pretty tired by the time they were done implementing it.

    Once a message for a multicast group actually gets to a host, the host needs to deliver it to the programs that are actually interested in it. Here, I suspect, implementers were too tired to do the right thing. Instead, they did a variety of lazy, easy things (depending on your platform). For example, some of them just visited every single open socket on the system that was subscribed to a multicast group and delivered the message to them.

    On other platforms, you'll sometimes find that a single multicast message is delivered to a single listening multicast socket more than once. And of course there's the popular issue of multicast messages never being delivered at all.

    Enjoy your wacky times in multicast land!