13

On a computer with both an active Wireless Card and a LAN-Port with a crossover cable hooked up to another machine running the same application, we need to send a UDP multicast over the LAN wire to the other computer. Using C# Sockets, Windows seems to try to route the message over the WLAN adapter every time.

Is there a way to specify what network interface to send a UDP multicast on?

Markus Roth
  • 343
  • 2
  • 5
  • 12

4 Answers4

18

Just as addendum to Nikolai answer: the problem with KB318911 is a dirty trick that user must provide necessary adapter index. While looking how to retrieve this adapter index I figured out such recipe:

NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in nics)
{
  IPInterfaceProperties ip_properties = adapter.GetIPProperties();
  if (!adapter.GetIPProperties().MulticastAddresses.Any())
    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

  // now we have adapter index as p.Index, let put it to socket option
  my_sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)IPAddress.HostToNetworkOrder(p.Index));
}

Full note at http://windowsasusual.blogspot.ru/2013/01/socket-option-multicast-interface.html

Yury Schkatula
  • 5,291
  • 2
  • 18
  • 42
  • Thanks; `adapter.SupportsMulticast` is useful to know about. NOTE: `p.Index` is sometimes `-1` for local loopback, when it should be `1`. and `p.Index` throws if the adapter has no index at all. – Jesse Chisholm Mar 13 '15 at 15:13
  • @JesseChisholm, thanks for the "-1" note - this makes perfect sense. Indeed, such case should be considered as well via extra "if" statement to make code robust. – Yury Schkatula Mar 13 '15 at 17:37
  • 4
    Wasted many hours when doing this for IPv6 so just a heads up: the interface index should be passed in host byte order when set on a IPv6 socket using SocketOptionLevel.IPv6. When set on IPv4 it should be in network byte order, this is easy to miss. IPv6 options: https://msdn.microsoft.com/en-us/library/windows/desktop/ms738574(v=vs.85).aspx IPv4 Options: https://msdn.microsoft.com/en-us/library/windows/desktop/ms738586(v=vs.85).aspx – danielnilsson9 Jul 22 '16 at 22:21
5

You are probably looking for SocketOptionName.MulticastInterface. Here's an article on MSDN that might help you.

Other then that if you update your local routing table to have an exact entry matching the multicast address and pointing to the right interface it should just work.

Nikolai Fetissov
  • 82,306
  • 11
  • 110
  • 171
3

Depending on what you're doing, there's a Win32 method that might help. It'll return the best interface for a given IP address. To get the default one (the 0.0.0.0), which is usually what you want for multicast, it's pretty easy:

P/Invoke signature:

[DllImport("iphlpapi.dll", CharSet = CharSet.Auto)]
private static extern int GetBestInterface(UInt32 DestAddr, out UInt32 BestIfIndex);

Then somewhere else:

// There could be multiple adapters, get the default one
uint index = 0;
GetBestInterface(0, out index);
var ifaceIndex = (int)index;

var client = new UdpClient();
client.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)IPAddress.HostToNetworkOrder(ifaceIndex));

var localEndpoint = new IPEndPoint(IPAddress.Any, <port>);
client.Client.Bind(localEndpoint);

var multicastAddress = IPAddress.Parse("<group IP>");
var multOpt = new MulticastOption(multicastAddress, ifaceIndex);
client.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multOpt);

var broadcastEndpoint = new IPEndPoint(IPAddress.Parse("<group IP>"), <port>);
byte[] buffer = ...
await client.SendAsync(buffer, buffer.Length, broadcastEp).ConfigureAwait(false);
Claire Novotny
  • 1,593
  • 1
  • 15
  • 19
0

If you are using UDPClient class, then this method forces the IGMP message out of the interface you desire (second parameter), even when binding doesn't work.

receiveUDPClient.JoinMulticastGroup(IPAddress.Parse("239.254.2.1"), IPAddress.Parse("192.168.6.1"));

Otherwise, MulticastOption(IPAddress, IPAddress) will work. The first parameter is the multicast address, the second address forces a localendpoint you specify to be used.

Goku
  • 1,565
  • 1
  • 29
  • 62