问题描述
我有下面的代码读取来自网络的多播消息,对于一个指定的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
我试过其他几件事情:
- 使用套接字接收UdpClient代替 - >没工作
- 设置一些另外的读者socketOption (DontRoute = 1,广播= 1) - >没工作
- 指定的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 5Here 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:
- Use a socket to receive instead of the UdpClient --> Didn't worked
- Set some addition socketOption on the reader(DontRoute =1, Broadcast=1) -->Didn't worked
- 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:从所有网络接口读取数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!