UDP:从所有网络接口读取数据

我有以下代码来读取来自网络的多播消息,用于指定的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 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

另一件事:如果我从我发送消息(localhost),在我所有的网卡上,我看到它们出现在我的两个网络接口上。 但是,如果我启动我的程序两次,只有第一个程序获取消息,而不是第二个。

编辑4

其他信息,在第一条评论之后:我有两张以太网卡,一张是10.10.24.78 ip,另一张是10.9.10.234 ip。 发送数据不是我,而是网络片段(带有此IP的端口5353是用于mDNS的已知多播地址,因此我应该从打印机,itunes,mac和我们创建的其他软件中获取流量)。 数据在ip 224.0.0.251和端口5353上进行了多播。

这是一个可用于在多个IP上发送数据的代码,但就像我描述的那样,如果你在本地启动它几乎可以工作(除了只有一个本地客户端接收消息)。

 private static void SendManuallyOnAllCards(int port, string multicastAddress, IEnumerable 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,Broadcast = 1) – >没有用
  3. 指定读者Socket必须使用的MulticastInterface(使用socketOption MulticastInterface) – >不起作用

我终于找到了怎么做!

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

由于我已经失去了3天,我认为值得一个例子:

 private static void ReceiveAsync(int port, string address, IEnumerable 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); } 

我希望有所帮助;)

您需要通过所有可用接口加入组播组。 默认情况下,传出的IGMP JOIN消息将根据单播路由表进行路由,这些表将通过“最便宜”的路由将其发送出去,使用哪个NIC访问该路由。 如果您的多播组可以通过多个路由来源,则需要进行迭代。

我有同样的问题,我想从我的所有网络接口接收多播。 正如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 sendClients = new List(); // 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列表,这样我就可以在所有网络接口上发送我的多播。