【问题标题】:Specifying what network interface an UDP multicast should go to in .NET在 .NET 中指定 UDP 多播应该转到的网络接口
【发布时间】:2020-01-02 23:04:50
【问题描述】:

在一台同时具有活动无线网卡和 LAN 端口的计算机上,通过交叉电缆连接到另一台运行相同应用程序的计算机,我们需要通过 LAN 线向另一台计算机发送 UDP 多播。使用 C# 套接字,Windows 似乎每次都尝试通过 WLAN 适配器路由消息。

有没有办法指定在哪个网络接口上发送 UDP 多播?

【问题讨论】:

  • 您找到解决方案了吗?我也有同样的问题。 MSDN 上的文章解决了您的问题吗?
  • @Gobliins 也没有为我工作:/ 任何解决方案?
  • @J4N 我确实使用了 udpclient 类(但也可以使用套接字)来加入特定适配器上的多播地址

标签: c# .net sockets udp multicast


【解决方案1】:

正如尼古拉回答的附录:KB318911 的问题是一个肮脏的技巧,用户必须提供必要的适配器索引。在寻找如何检索此适配器索引时,我想出了这样的秘诀:

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));
}

http://windowsasusual.blogspot.ru/2013/01/socket-option-multicast-interface.html的完整注释

【讨论】:

  • 谢谢; adapter.SupportsMulticast 很有用。注意:对于本地环回,p.Index 有时是 -1,而它应该是 1。如果适配器根本没有索引,则 p.Index 抛出。
  • @JesseChisholm,感谢您的“-1”注释 - 这很有意义。事实上,这种情况也应该通过额外的“if”语句来考虑,以使代码健壮。
  • 在为 IPv6 执行此操作时浪费了很多时间,所以请注意:当使用 SocketOptionLevel.IPv6 在 IPv6 套接字上设置时,接口索引应按主机字节顺序传递。在 IPv4 上设置时,它应该按网络字节顺序排列,这很容易被忽略。 IPv6 选项:msdn.microsoft.com/en-us/library/windows/desktop/… IPv4 选项:msdn.microsoft.com/en-us/library/windows/desktop/…
【解决方案2】:

您可能正在寻找SocketOptionName.MulticastInterfaceHere 是 MSDN 上的一篇文章,可能对您有所帮助。

除此之外,如果您更新本地路由表以具有与多播地址匹配并指向正确接口的确切条目,它应该可以正常工作。

【讨论】:

  • 链接已损坏。这个答案没用。
  • MSDN 链接应该被自动禁止。它们几乎总是坏掉
【解决方案3】:

根据您的操作,有一种 Win32 方法可能会有所帮助。它将返回给定 IP 地址的最佳接口。要获得默认值(0.0.0.0),这通常是您想要的多播,非常简单:

P/Invoke 签名:

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

然后在其他地方:

// 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);

【讨论】:

    【解决方案4】:

    如果您使用的是 UDPClient 类,则此方法会强制 IGMP 消息离开您想要的接口(第二个参数),即使绑定不起作用。

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

    否则,MulticastOption(IPAddress, IPAddress) 将起作用。第一个参数是多播地址,第二个地址强制使用您指定的本地端点。

    【讨论】:

      猜你喜欢
      • 2012-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-21
      • 1970-01-01
      • 2011-04-17
      相关资源
      最近更新 更多