在具有活动无线网卡和 LAN 端口的计算机上,通过交叉电缆连接到另一台运行相同应用程序的计算机,我们需要通过 LAN 线向另一台计算机发送 UDP 多播。使用 C# 套接字,Windows 似乎每次都尝试通过 WLAN 适配器路由消息。
有没有办法指定在哪个网络接口上发送 UDP 多播?
正如尼古拉回答的附录: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
您可能正在寻找SocketOptionName.MulticastInterface
. 这是 MSDN 上的一篇文章,可能会对您有所帮助。
除此之外,如果您更新本地路由表以具有与多播地址匹配并指向正确接口的确切条目,它应该可以正常工作。
根据您在做什么,有一种 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);
如果您使用的是 UDPClient 类,那么此方法会强制 IGMP 消息离开您想要的接口(第二个参数),即使绑定不起作用。
receiveUDPClient.JoinMulticastGroup(IPAddress.Parse("239.254.2.1"), IPAddress.Parse("192.168.6.1"));
否则,MulticastOption(IPAddress, IPAddress)
将工作。第一个参数是多播地址,第二个地址强制使用您指定的本地端点。