2013-03-07 30 views
5

我有下面的代碼讀取來自網絡的多播消息,在指定的IP +端口UDP:從所有網絡接口讀取數據

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 +端口(由兩個wireshark監視每個網絡適配器的實例確認)。我看到在這兩個網卡上有很多來自這些端口+ Ip)的流量。

的問題是,我的控制檯上,我只看到從一個網卡來的消息。

我雙用netstat檢查,我沒有任何其他的軟件我的監聽端口: enter image description here

那麼,爲什麼我獲得流量只從我的兩個網卡呢?

編輯

我甚至試過如下:

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

我也注意到了其他的怪了。如果我禁用接收所有數據的接口,然後啓動軟件,我現在從其他接口獲取數據。如果我再次激活界面並重新啓動軟件,我仍然可以在未禁用的卡上獲得流量。

而且我肯定知道,我已經對我回應說,僅連接到一個網絡(不能同時)

編輯3

另一件事設備:如果我發送消息從我(本地主機),在我所有的網卡上,我看到他們來到我的兩個網絡接口。但是,如果我開始我的程序兩次,只有第一個程序獲得消息,而不是第二個。

編輯4

其他信息,第一評論如下: 我有兩個網卡,一個與10.10.24.78知識產權,其他同10.9.10.234 IP。 這不是我發送數據,但網件(端口5353與此IP是一個知道用的mDNS組播地址,所以我應該從東西像打印機時,iTunes,蘋果獲得的流量,以及軟件的其他一些作品,我們創建了) 。數據是多播的IP 224.0.0.251和端口5353

這裏是你可以用它來發送關於severals的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

編輯6數據

我試了幾個其他的事情:

  1. 使用插座接受,而不是UdpClient - >沒工作
  2. 設置一些另外socketOption對讀者(DontRoute = 1,廣播= 1) - >沒工作
  3. 指定MulticastInterface讀卡器必須使用套接字(使用socketOption MulticastInterface) - >沒有工作
+0

什麼是你的接口(以太網,eth/wlan)?你在這些接口上有什麼IP?如果你能分析你是如何發送多播消息的話,那將會更有幫助。 – PCoder 2013-03-07 09:01:38

+0

@PCoder:謝謝你的評論,我在我最初的問題上添加了一些細節(編輯4) – J4N 2013-03-07 09:10:45

+0

你能告訴我們'route print'命令的輸出嗎? – PCoder 2013-03-07 09:22:50

回答

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 2013-03-07 10:25:30

+0

您必須迭代本地接口的IP地址並通過它們中的每一個進行連接。 – EJP 2013-03-07 22:50:32

+1

我想你沒有看到我的第二個代碼引用,這正是我正在做的。 – J4N 2013-03-08 06:39:08

2

我有,我想從我的所有網絡接口接收多播同樣的問題。正如EJP已經說了,你需要在UdpClient呼籲JoinMulticastGroup(IPAddress multicastAddr, IPAddress localAddress)所有網絡接口:

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 2016-01-12 22:02:28