Disclaimer: this is a short description of a code snippet primarily for myself because I had failed to find corresponding details in MSDN as well as on Google about SocketOptionName.MulticastInterface parameter values. Feel free to use it if you're experiencing the same lack of luck. Multicasts... You have to learn them right after generic sockets (aka unicasts) and massive spam-like broascasts. According to their nature, multicasts gather one-shot-to-many strength of broadcasting and can pass boundaries of nested networks like unicasts. The only weak side is knowledge "how to tune the socket". How many networks?
In old good days, main question for network-oriented code was: do you have a connection? In quite advanced cases you had to be interested about "is it LAN connection or dial-up modem?". What a happy times! Nova days, you have to be extremely worry about "how many possible connections are available" and "which of them are really up and running". Reason is simple:
- VPN connections (half-joke: dear Cisco, could you been so kind to fix your "Cisco VPN Client" software, even in XXI century?)
- Wi-Fi cards and dongles
- Two-LAN motherboards
- Virtual machines and other "virtual" network devices
In ideal world, network is automatically routed so every data packet will be sent most eficient way to the destination point. In practice, there are inevitable ambiguities and conflicts. Especially for multicasts. Default all-hearing ear
Sending a multicast means you use special IP address to use as a destination point, that's it. Other staff is trivial: create an UDP socket, use SendTo() function, read back every answer. It works? Yes, it works... works again and again... Oh, no, this time it stopped! Let me guess why: you opened a VPN connection to your workplace few moments ago...
By default, most operating systems use one and only one network interface to listen for multicast traffic. If you got another interface activated, there is a chance that your OS can decide new interface is more "important" in terms of multicasts so new multicast listener been elected. In most cases, VPN connections are treated as "more important" than generic ones, so you have all your multicast traffic passed to wrong wire. And with 99% probability, your admin is smart enough to cut off any optional data exchange via VPN due security restrictions (and traffic bills optimization as well). As long as multicasts are non-reliable UDP packets, there are no retransmits nor timeouts... So, you send multicast request and have no idea could you expect any response (and VPN gate will cut it off silently). To cure such "black hole" scenario, you need to set socket option "I want given interface as multicast ear" instead of default auto-election. Cure is known. Any pill for C#?
Despite big differences in operating systems and programming languages, network layer shares the same ideas on Windows and Linux, C++ and Python etc. So it's easy to find out that sockets provide such option as IP_MULTICAST_IF at IP_PROTO layer so you can put any of your local IP addresses as "multicast ear" with setsockopt() call.
At C#, there are the same ingredients:
my_sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
my_sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, ???);
Wait, but what we have to place as a last param?
MSDN does very common description for SetSocketOption last param "optionValue: A value of the option". SocketOptionName enumeration also stay away from answering anything other than "MulticastInterface: Set the interface for outgoing multicast packets". Not good... Help me, Google! Unfortunately, Google results provide a lot of forum discussions finally refering to KB318911. Full oh hope, you click it just to see this:
|When you use MulticastInterface as the value for the SocketOptionName enumeration, the optionValue expects an Index value of the particular Network Adapter or Interface. Note that there is currently no API in the .NET Framework to determine the index of a particular adapter. Therefore, the user must input the index value.|
Once found that article, I got big anger. "Arrrgh! Impossible! It can't be true!" idea stuck in my mind. And, scratching the head during few days, step by step I composed the following snippet: NetworkInterface nics = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in nics)
IPInterfaceProperties ip_properties = adapter.GetIPProperties();
continue; // most of VPN adapters will be skipped if (!adapter.SupportsMulticast)
continue; // multicast is meaningless for this type of connection
if (OperationalStatus.Up != adapter.OperationalStatus)
continue; // this adapter is off or not connected
IPv4InterfaceProperties p = adapter.GetIPProperties().GetIPv4Properties();
if (null == p)
continue; // IPv4 is not configured on this adapter
my_sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)IPAddress.HostToNetworkOrder(p.Index));
Looking back, the idea is simple: enumerate all network interfaces, skip every inapplicable, then get IP interface properties, get this "undocumented" adapter index. And don't forget about this low-level staff, HostToNetworkOrder() bytes swapper! Happy coding!