UDP:从所有网络接口读取数据(UDP: Read data from all network in

2019-07-21 03:48发布

我有下面的代码读取来自网络的多播消息,指定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 +端口未来两个网络适配器(通过监控每个网络适配器的Wireshark的两个实例证实)。 我上的wireshark看到很多这些端口+ IP)为网络卡上的通信量的。

问题是,我的控制台上,我只看到从一个网卡来的消息。

我双用netstat检查,我没有任何其他的软件我的监听端口:

那么,为什么我获得流量只从我的两个网卡呢?

编辑

我甚至试过如下:

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地址),但它仍然只显示来自一个网卡来的数据。

编辑2

我也注意到了其他的怪了。 如果我禁用我收到的所有数据,然后启动软件的界面,我现在得到来自其他接口数据。 如果我再次激活界面,并重新启动该软件,我仍然得到不停用卡上的流量。

我知道肯定了我在回应我只连接到一个网络设备,(不能同时)

编辑3

另一件事:如果我从我(本地主机)发送一个消息,我已经都上网卡,我看到他们对我的两个网络接口的到来。 但是,如果我开始我的计划的两倍,只有第一个PROGRAMM得到的消息,没有第二个。

编辑4

其他信息,第一评论如下:我有两个以太网卡,一个与10.10.24.78的IP,其他同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);
        }
    }
}

编辑5这里是我的结果route print (不知道命令),以及我的两个IP地址,我总是收到的数据10.9.10.234

编辑6

我尝试了其他几件事情:

  1. 使用一个插座接收,而不是UdpClient - >没工作
  2. 设置一些另外socketOption对读者(DontRoute = 1,广播= 1) - >没工作
  3. 指定MulticastInterface读者插座必须使用(使用socketOption MulticastInterface) - >没有工作

Answer 1:

我终于找到了如何做到这一点!

事实上,如果我保持完全相同的代码,但使用它与异步方法,它的工作! 我只是不明白为什么它不同步的方法工作(如果有人知道,欢迎您告诉我:))

自从我在这个失去了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);
}

我希望帮助;)



Answer 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的列表,以便我可以所有网络接口我多播。



Answer 3:

你需要通过所有可用的接口加入组播组。 缺省情况下,传出IGMP JOIN消息将根据单播路由表,这将它发送出去通过“最便宜的”路线,使用取NIC访问该路径被路由。 如果您的组播组可以通过这些途径的多于一个被采购,就需要进行迭代。



文章来源: UDP: Read data from all network interfaces