问题
I'm trying to send a multicast packet on all my network interfaces(2 LAN, one wifi). I initialy followed this tutorial.
The problem I encounter, is that it seems that the packet seems to be with only one of my IP address.
Here is my current code.
private static void SendOnAllCards(int port, String address)
{
using (Socket mSendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
new MulticastOption(IPAddress.Parse(address)));
mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
mSendSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
mSendSocket.Bind(new IPEndPoint(IPAddress.Any, port));
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(address), port);
mSendSocket.Connect(ipep);
byte[] bytes = Encoding.ASCII.GetBytes("This is my welcome message");
mSendSocket.Send(bytes, bytes.Length, SocketFlags.None);
}
}
I tried to do it manually:
private static void SendOnAllCards(int port, string remoteAddressSrc)
{
foreach (IPAddress remoteAddress in Dns.GetHostAddresses(Dns.GetHostName()).Where(i=>i.AddressFamily == AddressFamily.InterNetwork))
{
using (Socket mSendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
new MulticastOption(IPAddress.Parse(remoteAddressSrc)));
mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
mSendSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
mSendSocket.Bind(new IPEndPoint(IPAddress.Any, port));
IPEndPoint ipep = new IPEndPoint(remoteAddress, port);
mSendSocket.Connect(ipep);
byte[] bytes = Encoding.ASCII.GetBytes("This is my welcome message");
mSendSocket.Send(bytes, bytes.Length, SocketFlags.None);
}
}
}
This works, but it implies I've to create as many socket that I've IP(in this sample I create them on each send, but it's just a test), and I don't like the way I've to obtain all my IPs.
So what is the right way to do this?
Edit second bonus question: Why is this working when I specify the local ip in the Connect
, which specify the remote address, but doesn't on the Bind
?
回答1:
Seems that we have to iterate on network interfaces, make a Bind on the local IP and do a Send*To* call:
public void SendTestMessage()
{
foreach (IPAddress localIp in
Dns.GetHostAddresses(Dns.GetHostName()).Where(i => i.AddressFamily == AddressFamily.InterNetwork))
{
IPAddress ipToUse = localIp;
using (var mSendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
new MulticastOption(_multicastIp, localIp));
mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255);
mSendSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
mSendSocket.MulticastLoopback = true;
mSendSocket.Bind(new IPEndPoint(ipToUse, _port));
byte[] bytes = Encoding.ASCII.GetBytes("This is my welcome message");
var ipep = new IPEndPoint(_multicastIp, _port);
mSendSocket.SendTo(bytes, ipep);
}
}
}
回答2:
You could find the network adapters using the WMI class Win32_NetworkAdapter
. You might have to refine the results that querying for instances of that brings, because there are many 'virtual adapters' created by both windows and third party software.
I wrote up a quick posh script to retreive the adapters using WMI. This should only display adapaters that have IP addresses. This is just to show the WMI information that you could query to retreive the activate adapeters.
$networkadapters = @(Get-CimInstance -ClassName Win32_NetworkAdapter -Property *)
$networkadapters_configs = @($networkadapters | Get-CimAssociatedInstance -ResultClassName Win32_NetworkAdapterConfiguration)
0..($networkadapters.Length-1) | %{
if($networkadapters_configs[$_].IPAddress -gt '') {
Write-Output "Adapter #$($_)"
Write-Output $networkadapters[$_]
Write-Output "Config #$($_)"
Write-Output $networkadapters_configs[$_]
}
}
来源:https://stackoverflow.com/questions/15251242/send-an-udp-multicast-packet-on-all-my-ips