2013-03-07 3 views
5

Я следующий код для чтения многоадресного сообщения, поступающего из сети, на определенный IP + PortUDP: Считывание данных из всех сетевых интерфейсов

private static void ReceiveMessages(int port, string ip, CancellationToken token) 
{ 
    Task.Factory.StartNew(() => 
     { 
      using (var mUdpClientReceiver = new UdpClient()) 
      { 
       var mReceivingEndPoint = new IPEndPoint(IPAddress.Any, port); 
       mUdpClientReceiver.ExclusiveAddressUse = false; 
       mUdpClientReceiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 
       mUdpClientReceiver.ExclusiveAddressUse = false; 
       mUdpClientReceiver.Client.Bind(mReceivingEndPoint); 
       mUdpClientReceiver.JoinMulticastGroup(IPAddress.Parse(ip), 255); 

       while (!token.IsCancellationRequested) 
       { 
        byte[] receive = mUdpClientReceiver.Receive(ref mReceivingEndPoint); 

        Console.WriteLine("Message received from {0} ",mReceivingEndPoint); 
       } 
      } 
     }); 
} 

Я два сетевых адаптера, с которого Я данные, поступающие на этот многоадресный IP-порт (подтвержденный двумя экземплярами wirehark, которые контролируют каждый сетевой адаптер). Я вижу на wirehark много трафика, идущего на этих портах + Ip) для обеих сетевых карт.

Проблема в том, что на моей консоли я вижу только сообщения, поступающие с одной сетевой карты.

Я проверил с NetStat, у меня нет никакого другого программного обеспечения прослушивания на мой порт: enter image description here

Так почему я получаю трафик только один из двух моих сетевых карт?

EDIT:

Я даже попробовал следующее:

private static void ReceiveMessages(int port, string ip, CancellationToken token, IEnumerable<IPAddress> ipAddresses) 
{ 
    foreach (IPAddress ipAddress in ipAddresses) 
    { 
     IPAddress ipToUse = ipAddress; 
     Task.Factory.StartNew(() => 
     { 
      using (var mUdpClientReceiver = new UdpClient()) 
      { 

       var mReceivingEndPoint = new IPEndPoint(ipToUse, port); 
       mUdpClientReceiver.ExclusiveAddressUse = false; 
       mUdpClientReceiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 
       mUdpClientReceiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); 
       mUdpClientReceiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1); 
       mUdpClientReceiver.ExclusiveAddressUse = false; 
       mUdpClientReceiver.Client.Bind(mReceivingEndPoint); 
       mUdpClientReceiver.JoinMulticastGroup(IPAddress.Parse(ip), 255); 
       Console.WriteLine("Starting to listen on "+ipToUse); 
       while (!token.IsCancellationRequested) 
       { 
        byte[] receive = mUdpClientReceiver.Receive(ref mReceivingEndPoint); 

        Console.WriteLine("Message received from {0} on {1}", mReceivingEndPoint,ipToUse); 
       } 
      } 
     }); 
    } 
} 

Я вижу «Начиная слушать на theCorrectIP» дважды (для моих двух IP-адресов), но она по-прежнему отображаются только данные, поступающие с одной сетевой карты.

EDIT 2

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

И я знаю, что я имею устройства, реагирующие на меня, которые подключены только к одной сети (не оба)

EDIT 3

Еще одна вещь: если я посылаю сообщение от меня (localhost), на всей сетевой карте, которая у меня есть, я вижу, что они появляются на моих двух сетевых интерфейсах. НО, если я начну свою программу дважды, только первая программа получит сообщения, а не вторую.

Edit 4

Дополнительная информация, после первого комментария: Я две сетевые карты, один с 10.10.24.78 IP, а другой с 10.9.10.234 ф. Это не я посылаю данные, а фрагменты сети (порт 5353 с этим ip - это многоадресный адрес, используемый для mDNS, поэтому я должен получать трафик от таких вещей, как принтер, itunes, macs и некоторые другие части программного обеспечения, которые мы создали) , Данные многоястны на ip 224.0.0.251 и порт 5353.

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

private static void SendManuallyOnAllCards(int port, string multicastAddress, IEnumerable<IPAddress> ipAddresses) 
{ 
    foreach (IPAddress remoteAddress in ipAddresses) 
    { 
     IPAddress ipToUse = remoteAddress; 
     using (var mSendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) 
     { 
      mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, 
             new MulticastOption(IPAddress.Parse(multicastAddress))); 
      mSendSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 255); 
      mSendSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 

      var ipep = new IPEndPoint(ipToUse, port); 
      //IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(multicastAddress), port); 
      mSendSocket.Bind(ipep); 
      mSendSocket.Connect(ipep); 


      byte[] bytes = Encoding.ASCII.GetBytes("This is my welcome message"); 
      mSendSocket.Send(bytes, bytes.Length, SocketFlags.None); 
     } 
    } 
} 

EDIT 5 Вот результат моего route print (Не знаю, что команда), и на моих двух IP-адресов, я всегда получаю данные о 10.9.10.234 enter image description here

Edit 6

Я попробовал несколько других вещей:

  1. Используйте сокет получить вместо UdpClient -> Не работал
  2. Установите некоторые добавления socketOption на читателя (DontRoute = 1, Broadcast = 1) -> Не работал
  3. Specify в MulticastInterface что считыватель Socket должен использовать (используя socketOption MulticastInterface) -> Не работает
+0

Каковы ваши интерфейсы (ethernet, eth/wlan)? И какие IP-адреса у вас есть на этих интерфейсах? Было бы более полезно, если бы вы могли проанализировать, как вы отправляете многоадресное сообщение. – PCoder

+0

@PCoder: Спасибо за комментарий, я добавил некоторые подробности по моему первоначальному вопросу (Edit 4) – J4N

+0

И можете ли вы показать нам вывод команды 'route print'? – PCoder

ответ

5

Я наконец нашел, как это сделать!

Фактически, если я сохраняю точно такой же код, но используя его с асинхронными методами, он работает !!! Я просто не могу понять, почему он не работает с методом синхронизации (если кто-то знает, вы можете мне рассказать :))

Поскольку я потерял 3 дня на этом, я думаю, что это стоит пример :

private static void ReceiveAsync(int port, string address, IEnumerable<IPAddress> localAddresses) 
{ 
    IPAddress multicastAddress = IPAddress.Parse(address); 
    foreach (IPAddress localAddress in localAddresses) 
    { 
     var udpClient = new UdpClient(AddressFamily.InterNetwork); 
     udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 
     udpClient.Client.Bind(new IPEndPoint(localAddress, port)); 
     udpClient.JoinMulticastGroup(multicastAddress, localAddress); 
     udpClient.BeginReceive(OnReceiveSink, 
           new object[] 
            { 
             udpClient, new IPEndPoint(localAddress, ((IPEndPoint) udpClient.Client.LocalEndPoint).Port) 
            }); 
    } 
} 

И метод асинхронной:

private static void OnReceiveSink(IAsyncResult result) 
{ 
    IPEndPoint ep = null; 
    var args = (object[]) result.AsyncState; 
    var session = (UdpClient) args[0]; 
    var local = (IPEndPoint) args[1]; 

    byte[] buffer = session.EndReceive(result, ref ep); 
    //Do what you want here with the data of the buffer 

    Console.WriteLine("Message received from " + ep + " to " + local); 

    //We make the next call to the begin receive 
    session.BeginReceive(OnReceiveSink, args); 
} 

Я надеюсь, что помогает;)

2

Вам необходимо присоединиться к группе многоадресной передачи через все доступные интерфейсы. По умолчанию исходящее сообщение IGMP JOIN будет маршрутизироваться в соответствии с таблицами одноадресной маршрутизации, которые отправят его через «самый дешевый» маршрут, используя тот, который NIC обращается к этому маршруту. Если ваша многоадресная группа может быть отправлена ​​через несколько маршрутов, вам необходимо выполнить итерацию.

+0

Я не уверен, что это 'mUdpClientReceiver.JoinMulticastGroup (IPAddress.Parse (ip), 255);', который делается для всех UdpClient, делает это, нет? Если нет, как мне это сделать? – J4N

+0

Вы должны перебирать IP-адреса локальных интерфейсов и присоединяться через каждый из них. – EJP

+1

Я думаю, что вы не видели мою вторую кодовую цитату, это именно то, что я делаю. – J4N

2

у меня была та же проблема, что я хотел получить многоадресных от всех моих сетевых интерфейсов. Как EJP уже сказал, вам нужно позвонить JoinMulticastGroup(IPAddress multicastAddr, IPAddress localAddress) на UdpClient для всех сетевых интерфейсов:

int port = 1036; 
IPAddress multicastAddress = IPAddress.Parse("239.192.1.12"); 

client = new UdpClient(new IPEndPoint(IPAddress.Any, port)); 

// list of UdpClients to send multicasts 
List<UdpClient> sendClients = new List<UdpClient>(); 

// join multicast group on all available network interfaces 
NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); 

foreach (NetworkInterface networkInterface in networkInterfaces) 
{ 
    if ((!networkInterface.Supports(NetworkInterfaceComponent.IPv4)) || 
     (networkInterface.OperationalStatus != OperationalStatus.Up)) 
    { 
     continue; 
    } 

    IPInterfaceProperties adapterProperties = networkInterface.GetIPProperties(); 
    UnicastIPAddressInformationCollection unicastIPAddresses = adapterProperties.UnicastAddresses; 
    IPAddress ipAddress = null; 

    foreach (UnicastIPAddressInformation unicastIPAddress in unicastIPAddresses) 
    { 
     if (unicastIPAddress.Address.AddressFamily != AddressFamily.InterNetwork) 
     { 
      continue; 
     } 

     ipAddress = unicastIPAddress.Address; 
     break; 
    } 

    if (ipAddress == null) 
    { 
     continue; 
    } 

    client.JoinMulticastGroup(multicastAddress, ipAddress); 

    UdpClient sendClient = new UdpClient(new IPEndPoint(ipAddress, port)); 
    sendClients.Add(sendClient); 
} 

Я также создать список UdpClients, так что я могу отправить мои многоадресных на всех сетевых интерфейсах.

+0

Thnks, я нашел это полезным – KGCybeX

Смежные вопросы