Широковещательное сообщение UDP ко всем доступным сетевым платам

Если Вы не находитесь на SQL Server 2008, и у Вас есть некоторые веские причины помещения определенных файлов изображений в базе данных, то Вы могли взять "и" подход и использовать файловую систему в качестве временного кэша и использовать базу данных в качестве главного репозитория.

, Например, Ваша бизнес-логика может проверить, существует ли файл изображения на диске прежде, чем подать ее, получая от базы данных при необходимости. Это покупает Вас возможность нескольких веб-серверов и меньшего количества синхронизирующих проблем.

12
задан Rex Logan 9 July 2009 в 01:33
поделиться

2 ответа

На самом деле это сложнее, чем кажется, потому что, если у вас более одного интерфейса, широковещательные сообщения не всегда будут поступать на все интерфейсы. Чтобы обойти это, я создал этот класс.

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 заключается в том, что они не будут маршрутизироваться через какие-либо шлюзы. Чтобы обойти это, вы можете создать список IP-адресов , а затем пройти через цикл и отправить. Кроме того, поскольку отправка может завершиться ошибкой из-за сетевых проблем, которые вы не можете контролировать, у вас также должен быть блок 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
 }

Изменить: см. Выше изменение одноадресной рассылки с несколькими интерфейсами, а также Проблема Попытка одноадресной рассылки пакетов в доступные сети.

17
ответ дан 2 December 2019 в 07:22
поделиться

Если вы отправляете сообщение на определенный IP-адрес, то вы выполняете одноадресную рассылку, а не широковещательную рассылку.

1
ответ дан 2 December 2019 в 07:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: