Это на самом деле сложнее, чем кажется, потому что, если у вас более одного интерфейса, широковещательные передачи не всегда выходят на все интерфейсы. Чтобы обойти это, я создал этот класс.
public class MyUdpClient : UdpClient
{
public MyUdpClient() : base()
{
//Calls the protected Client property belonging to the UdpClient base class.
Socket s = this.Client;
//Uses the Socket returned by Client to set an option that is not available using UdpClient.
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
}
public MyUdpClient(IPEndPoint ipLocalEndPoint) : base(ipLocalEndPoint)
{
//Calls the protected Client property belonging to the UdpClient base class.
Socket s = this.Client;
//Uses the Socket returned by Client to set an option that is not available using UdpClient.
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
}
}
Затем, чтобы отправить UDP-пакет через широковещательную рассылку, я использую что-то вроде следующего. Я использую IPAddress.Broadcast
и MyUdpClient
, который отличается от вашего кода.
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(LocalIP), 0);
IPEndPoint targetEndPoint = new IPEndPoint(IPAddress.Broadcast, iTargetPort);
MyUdpClient sendUdpClient = new MyUdpClient(localEndPoint);
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);
Кроме того, следует отметить, что при использовании конкретного ipaddress
вместо трансляции таблица маршрутизации только отправляет его через интерфейс, соответствующий адрес.
В вашем примере используется одноадресная рассылка. Вам нужно установить LocalIP
на IP-адрес локального интерфейса, который вы хотите отправить. С тремя интерфейсами у вас будет три локальных IP-адреса, и вам нужно выбрать правильный для использования.
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(LocalIP), 0);
IPEndPoint targetEndPoint = new IPEndPoint(TargetIP, iTargetPort);
MyUdpClient sendUdpClient = new MyUdpClient(localEndPoint);
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);
Поскольку маршрут отключен, вы можете увидеть его на всех интерфейсах, но вам нужно будет протестировать его для случая одноадресной передачи.
Если вам не нужен IP-адрес отправки, вы можете использовать следующий код.
IPEndPoint targetEndPoint = new IPEndPoint(TargetIP, iTargetPort);
MyUdpClient sendUdpClient = new MyUdpClient();
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);
или для трансляции
IPEndPoint targetEndPoint = new IPEndPoint(IPAddress.Broadcast, iTargetPort);
MyUdpClient sendUdpClient = new MyUdpClient();
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);
Проблема с IPAddress.Broadcast
том, что они не будут маршрут через любые шлюзы. Чтобы обойти это, вы можете создать список IPAddresses
, а затем выполнить цикл и отправить. Кроме того, поскольку Send может выйти из строя для сетевых проблем, которые вы не можете контролировать, также должен быть блок try/catch.
ArrayList ip_addr_acq = new ArrayList();
ip_addr_acq.Add(IPAddress.Parse("10.1.1.1")); // add to list of address to send to
try
{
foreach (IPAddress curAdd in ip_addr_acq)
{
IPEndPoint targetEndPoint = new IPEndPoint(curAdd , iTargetPort);
MyUdpClient sendUdpClient = new MyUdpClient();
int numBytesSent = sendUdpClient.Send(CombineHeaderBody, CombineHeaderBody.Length, targetEndPoint);
Thread.Sleep(40); //small delay between each message
}
}
catch
{
// handle any exceptions
}
Edit: см.выше изменения в одноадресно с несколькими интерфейсами, а также Problem Trying to unicast packets to available networks.
Вы можете уточнить больше, что вы хотите пытаетесь дел. –
Мое приложение отправит сообщения в приложение в 10+ системах. В которых все системы находятся в трех разных сетевых картах. Как 10.1.x.x/10.2.x.x/10.4.x.x Я могу получить сообщение только в одной сетевой карте 10.1.x.x, но не в других двух сетевых картах. Поэтому я хочу проверить доступность сетевой карты, а затем отправить сообщение. Благодарю. – Anuya
, так это сообщение, нужно только проверить доступность сети или иметь какую-то другую полезную нагрузку/смысл? –