UDP:从所有网络接口读取数据 [英] UDP: Read data from all network interfaces

查看:158
本文介绍了UDP:从所有网络接口读取数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有下面的代码读取来自网络的多播消息,对于一个指定的IP +端口



 私有静态无效ReceiveMessages(INT口,串IP,令牌的CancellationToken)
{
Task.Factory.StartNew(()=>
{
使用(VAR mUdpClientReceiver =新UdpClient() )
{
变种mReceivingEndPoint =新IPEndPoint(IPAddress.Any,口);
mUdpClientReceiver.ExclusiveAddressUse = FALSE;
mUdpClientReceiver.Client.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress ,真正的);
mUdpClientReceiver.ExclusiveAddressUse = FALSE;
mUdpClientReceiver.Client.Bind(mReceivingEndPoint);
mUdpClientReceiver.JoinMulticastGroup(IPAddress.Parse(IP),255);

在(token.IsCancellationRequested!)
{
字节[] =接收mUdpClientReceiver.Receive(REF mReceivingEndPoint);

Console.WriteLine(,mReceivingEndPoint从{0}接收到的消息);
}
}
});
}



我两个网络适配器从我数据的该多播到来IP +端口(通过监控每个网络适配器的Wireshark的两个实例证实)。我上的wireshark看到很多这些端口+ IP)为网络卡的到来流量。



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



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



那么,为什么我得到仅从我的两个网卡和一个流行?



修改



我甚至试过如下:

 私有静态无效ReceiveMessages(INT口,串IP,的CancellationToken令牌,IEnumerable的< ip地址与GT; ipAddresses)
{
的foreach (ip地址ip地址在ipAddresses)$ b $乙:{
ip地址= ipToUse ip地址,
Task.Factory.StartNew =>(();使用(VAR mUdpClientReceiver
{
=新UdpClient())
{

VAR mReceivingEndPoint =新IPEndPoint(ipToUse,口);
mUdpClientReceiver.ExclusiveAddressUse = FALSE;
mUdpClientReceiver.Client.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress,真正的);
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(开始听的+ ipToUse);
,而(token.IsCancellationRequested! )
{
字节[] =接收mUdpClientReceiver.Receive(REF mReceivingEndPoint); ;

Console.WriteLine(,mReceivingEndPoint,ipToUse从{0}在{1}收到消息)
}
}
});
}
}



我看到开始监听theCorrectIP两次(对于我的两个IP地址),但它仍然只显示来自一个网卡来的数据。



编辑2



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



和我肯定知道,我已经进行了回复装置对我来说,只连接到一个网络(而不是两者)



修改3



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



修改4



其他信息,下面的第一个注释:
我有两个以太网卡,一个具有 10.10.24.78 IP,其余与 10.9.10.234 IP。
这不是我发送数据,但网件(端口 5353 这个IP是知道使用的mDNS组播地址,所以我应该从事情接收流量像打印机时,iTunes,Mac电脑和其他一些作品的软件,我们创建)。数据是多播的IP
224.0.0.251 和端口 5353



下面是你可以用它来发送的severals的IP数据的代码,但像我描述的,如果你一开始就在当地几乎工作(除了只有一个本地客户端接收消息)。

 私有静态无效SendManuallyOnAllCards(INT口,串multicastAddress,IEnumerable的< ip地址> ipAddresses)
{
的foreach (ip地址remoteAddress在ipAddresses)
{
ip地址ipToUse = remoteAddress;
使用(VAR mSendSocket =新的Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp))
{
mSendSocket.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.AddMembership,
新MulticastOption(IPAddress.Parse(multicastAddress)));
mSendSocket.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.MulticastTimeToLive,255);
mSendSocket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress,真正的);

变种IPEP =新IPEndPoint(ipToUse,口);
// IPEndPoint IPEP =新IPEndPoint(IPAddress.Parse(multicastAddress),端口);
mSendSocket.Bind(IPEP);
mSendSocket.Connect(IPEP);


字节[]字节= Encoding.ASCII.GetBytes(这是我欢迎信息);
mSendSocket.Send(字节,bytes.Length,SocketFlags.None);
}
}
}

修改5
这是我的 route print命令的结果(不知道命令),并在我的两个IP地址,我总是收到的数据 10.9.10.234



修改6



我试过其他几件事情:




  1. 使用套接字接收UdpClient代替 - >没工作

  2. 设置一些另外的读者socketOption (DontRoute = 1,广播= 1) - >没工作

  3. 指定的MulticastInterface读者插座必须使用(使用socketOption MulticastInterface) - >没有工作


解决方案

我终于找到了该怎么办呢!



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



既然我已经失去了在这3天,我认为这值得一个例子:

 私有静态无效ReceiveAsync(INT口,串地址,IEnumerable的< ip地址> ; localAddresses)
{
ip地址multicastAddress = IPAddress.Parse(地址);
的foreach(ip地址将localAddress在localAddresses)
{
变种udpClient =新的UdpClient(AddressFamily.InterNetwork);
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress,真正的);
udpClient.Client.Bind(新IPEndPoint(将localAddress,口));
udpClient.JoinMulticastGroup(multicastAddress,将localAddress);
udpClient.BeginReceive(OnReceiveSink,
新的对象[]
{
udpClient,新IPEndPoint(将localAddress,((IPEndPoint)udpClient.Client.LocalEndPoint).Port)
});
}
}

和异步方法:

 私有静态无效OnReceiveSink(IAsyncResult的结果)
{
IPEndPoint EP = NULL;
变参=(对象[])result.AsyncState;
变种会话=(UdpClient)ARGS [0];
变种本地=(IPEndPoint)ARGS [1];

字节[]缓冲= session.EndReceive(结果,文献EP);
//你想要的东西在这里与缓冲区

Console.WriteLine的可数据(+ EP +从收到的消息到+本地);

//我们做下一次调用的开始领取
session.BeginReceive(OnReceiveSink,参数);
}



我希望帮助;)


I've the following code to read multicast message coming from the network, for a specified IP+Port

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

I've two network adapter from which I've data coming on this multicast ip+port(confirmed by two instances of wireshark monitoring each network adapter). I see on wireshark a lot of traffic coming on those port+Ip) for both network cards.

The problem is that on my console, I only see messages coming from one network card.

I double checked with netstat, I don't have any other software listening on my port:

So why am I getting traffic from only one of my two network cards?

EDIT:

I even tried the following:

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

I see the "Starting to listen on theCorrectIP" twice(for my two IPs), but it still display only data coming from one network card.

EDIT 2

I did notice something else that is strange too. If I disable the interface on which I receive all data, and then start the software, I now get data from the other interface. If I activate again the interface and restart the software, I still get the traffic on the non-deactivated card.

And I know for sure that I've devices that respond to me, that are connected only to one network(not both)

EDIT 3

Another thing: if I send a message from me(localhost), on all network card that I've, I see them coming on my two network interfaces. BUT, if I start my program twice, only the first programm get messages, not the second one.

Edit 4

Additional info, following the first comment: I've two ethernet cards, one with the 10.10.24.78 ip, the other with the 10.9.10.234 ip. It's not me that send data, but network pieces(the port 5353 with this ip is a know multicast address used for mDNS, so I should receive traffic from things like printer, itunes, macs, and some other pieces of software we created). Data are multicasted on the ip 224.0.0.251 and port 5353.

Here is a code that you could use to send data on severals IPs, but like I described, if you start it in local it almost works(except that only one local client receive the message).

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 Here is the result of my route print(Didn't know that command), and on my two IPs, I always receive data on the 10.9.10.234

Edit 6

I tried several other things:

  1. Use a socket to receive instead of the UdpClient --> Didn't worked
  2. Set some addition socketOption on the reader(DontRoute =1, Broadcast=1) -->Didn't worked
  3. Specify the MulticastInterface that the reader Socket has to use(using socketOption MulticastInterface) --> Didn't work

解决方案

I finally found how to do it!

In fact, if I keep exactly the same code, but using it with async methods, it work!!! I just can't understand why it doesn't work with sync method(if someone knows, you're welcome to tell me :) )

Since I've lost 3 days on this, I think it worth an example:

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

And the async method:

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

I hope that helps ;)

这篇关于UDP:从所有网络接口读取数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆