6

指定されたIP+ポートについて、ネットワークからのマルチキャストメッセージを読み取るための次のコードがあります

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+portでデータを取得する2つのネットワークアダプターがあります(各ネットワークアダプターを監視するwiresharkの2つのインスタンスによって確認されます)。Wiresharkでは、両方のネットワークカードでこれらのポート+ IP)に大量のトラフィックが発生しています。

問題は、コンソールに1つのネットワークカードからのメッセージしか表示されないことです。

netstatで再確認しましたが、ポートでリッスンしている他のソフトウェアはありません。 ここに画像の説明を入力してください

では、なぜ2枚のネットワークカードのうち1枚だけからトラフィックを取得しているのでしょうか。

編集

私も次のことを試しました:

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);
                }
            }
        });
    }
}

「CorrectIPでのリッスンの開始」が2回表示されますが(2つのIPの場合)、1つのネットワークカードからのデータのみが表示されます。

編集2

私も奇妙なことに気づきました。すべてのデータを受信するインターフェイスを無効にしてからソフトウェアを起動すると、他のインターフェイスからデータを取得できるようになります。インターフェイスを再度アクティブにしてソフトウェアを再起動しても、非アクティブ化されていないカードでトラフィックが発生します。

そして、私は自分に応答するデバイスがあり、1つのネットワーク(両方ではない)にのみ接続されていることを確かに知っています

編集3

もう1つのこと:私(localhost)からメッセージを送信すると、私が持っているすべてのネットワークカードで、2つのネットワークインターフェイスにメッセージが届くのがわかります。しかし、プログラムを2回起動すると、最初のプログラムだけがメッセージを受け取り、2番目のプログラムはメッセージを受け取りません。

編集4

最初のコメントに続く追加情報:2つのイーサネットカードがあります。1つは10.10.24.78IPを使用し、もう1つはIPを使用し10.9.10.234ます。データを送信するのは私ではなく、ネットワーク部分です(5353このIPを持つポートは、mDNSに使用される既知のマルチキャストアドレスであるため、プリンター、iTunes、Mac、および作成したその他のソフトウェアからトラフィックを受信する必要があります)。データはIP 224.0.0.251とポートでマルチキャストされます5353

これは、いくつかのIPでデータを送信するために使用できるコードですが、前述のように、ローカルで開始すると、ほとんど機能します(ただし、1つのローカルクライアントのみがメッセージを受信します)。

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);
        }
    }
}

編集5 これが私のroute print(そのコマンドを知らなかった)結果です、そして私の2つのIPで、私は常にデータを受け取ります10.9.10.234 ここに画像の説明を入力してください

編集6

私は他のいくつかのことを試しました:

  1. UdpClientの代わりに受信するソケットを使用してください->機能しませんでした
  2. リーダーに追加のsocketOptionを設定します(DontRoute = 1、Broadcast = 1)->機能しませんでした
  3. リーダーSocketが使用する必要のあるMulticastInterfaceを指定します(socketOption MulticastInterfaceを使用)->機能しませんでした
4

3 に答える 3

6

すべてのネットワークインターフェイスからマルチキャストを受信したいという同じ問題がありました。JoinMulticastGroup(IPAddress multicastAddr, IPAddress localAddress)EJPがすでに述べたように、すべてのネットワークインターフェイスに対して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);
}

また、すべてのネットワークインターフェイスでマルチキャストを送信できるように、UdpClientのリストを作成しています。

于 2013-04-04T10:42:28.077 に答える
5

私はついにそれを行う方法を見つけました!

実際、まったく同じコードを保持しているが、非同期メソッドで使用すると、機能します!!! なぜsyncメソッドで動作しないのか理解できません(誰かが知っているなら、教えてください:))

私はこれで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);
}

それがお役に立てば幸いです;)

于 2013-03-08T09:57:37.830 に答える
3

使用可能なすべてのインターフェイスを介してマルチキャストグループに参加する必要があります。デフォルトでは、発信IGMP JOINメッセージは、ユニキャストルーティングテーブルに従ってルーティングされます。ユニキャストルーティングテーブルは、そのルートにアクセスするNICを使用して、「最も安い」ルートを介してメッセージを送信します。マルチキャストグループがこれらのルートの複数を介して送信される可能性がある場合は、反復する必要があります。

于 2013-03-07T10:16:42.907 に答える