UDP client multicast address - c#

I am developing a system that is sending UDP packets using LWIP on Nios processor. I have developed a C# application to allow visualization of the received data.
The issue that I am having is on receiving data on the C# application when sending to multicast addresses. On the com+uter running the C# app I am able to visualized the incoming packets addressed for IP 225.0.0.1(multicast address) but my C# app does not receive them.
The C# app receives data sent to a network address, for example 192.168.0.100 or when data is sent to 255.255.255.255 (in this case I can run the app in two diferrent computers and both receive the same data).
I have read several answers here on the forum and tried them all.
The code that I am using currently is:
UdpClient udpClientImage;
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 8884);
udpClientImage = new UdpClient(RemoteIpEndPoint);
udpClientImage.EnableBroadcast = true;
IPAddress m_GrpAddr;
m_GrpAddr = IPAddress.Parse("225.0.0.1");
udpClientImage.JoinMulticastGroup(m_GrpAddr);
while (true)
{
Byte[] receiveBytes = udpClientImage.Receive(ref RemoteIpEndPoint);
senderIPAddress = RemoteIpEndPoint.Address;
string returnData = Encoding.ASCII.GetString(receiveBytes);
}
Am I missing something in order to receive the multicast addresses?
Any help would be welcome,

Your UdpClient has to join the multicast group to listen. It's not automatic.
udpClientImage.JoinMulticastGroup(multicastAddress);
See MSDN for more information about this method.

The address passed into the constructor is the NIC(s) that you are listening on. The address passed into the Receive method is a filter and gets updated to reflect the source of the message. I don't think you want to reuse that one, and I don't think it should be the same as the bound NIC.

Try disabling rp_filter on the receiving system
You can check out this post:
UDP multicast client does not see UDP multicast traffic generated by tcpreplay

Related

Multible programs/instances using the same UDP Port in C#

I am struggling with a bit of network magic and hoped someone would be able to explain me what is happening.
I am trying to reuse udp ports. So if I have multible programs listening on the same udp port i want both of the applications to receive the data send by a different device.
Using the following code I'am able to achive just that:
IPEndPoint localEndoint = new IPEndPoint(IPAddress.Any, 67); //the local endpoint used to listen to port 67
//Create a new UDP Client and bind it to port 67
DhcpSniffer = new UdpClient();
DhcpSniffer.ExclusiveAddressUse = false; //Allow multible clients to connect to the same socket
DhcpSniffer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); // Connect even if socket/port is in use
DhcpSniffer.Client.Bind(localEndoint);
DhcpSniffer.Client.ReceiveTimeout = Timeout;
//receive on port 67
dhcpPacket = DhcpSniffer.Receive(ref localEndoint);
Both of my programs can listen to DHCP messages in the network and don't block each other.
Now i want to do the same thing with port 15120 where a RTP video stream is streamed to. However this does not work. I am using the same code but with no success only one application at a time can receive the stream, the other will run in a timeout.
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, port);
//Create a new UDP Client and bind it to port 15120
udpReceiver = new UdpClient();
udpReceiver.ExclusiveAddressUse = false; //this is an attempt to receive the stream on mutlible instances...this works for DHCP but not for RTP for some reason....
udpReceiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); // Connect even if socket/port is in use
udpReceiver.Client.ReceiveTimeout = timeout; //set the sockete timeout
udpReceiver.Client.Bind(RemoteIpEndPoint); //bind to the port from any IP
//receive packets on port 15120
Byte[] receiveBytes = udpReceiver.Receive(ref RemoteIpEndPoint);
I hope somebody is able to shine a light on my confusion
Update:
I found out it works with DHCP because it is send to the broadcast IP (255.255.255.255). Now I need to find out how i can change the Socket behaviour to treat my RTP stream as if it was broadcasted so i can see it in two application at the same time. (Yes I could configure my stream-source to broadcast, but this is not the goal of this).
The goal is to reconfigure the Socket to behave as explained. Not to save the stream on a harddrive or redirect it using the local host.
First, its not possible to have multiple programs listen on the same port (As far as I know it's a big security conflict)
What you can do tough, is use a NetworkManager that listen on you port (Lets call it port 8080) who will then redirect the information to you apps ports (App1 could use port 8081 and App2 use port 8082). Either you write your own, using Flask to listen on 8080 and then rerouting the package to localhost:8081 and localhost:8082 could be a simple and fast solution.
Doing this would help you secure the network and you can redirect to as many ports as you need, pretty much like a docker swarm would balance the incoming network to its cluster.
It is not possible with multible programs to access the data from a unicast UDP package, it works only with multicast, there is no "easy" way around this by reconfiguring the UdpClient

Multicast Packets not Received with Multiple NICs

I am having an issue I can't seem to sort out and after looking through the site I didn't see my exact issue so here we go.
I have a PC with multiple NIC adapters. One is set to 192.168.6.1 and the other is set to 192.168.2.90, both have the same subnet mask of 255.255.0.0. Both NICs are plugged into the same network switch (not managed, just a 32 port switch). Residing on the same network are multiple PCs with the same subnet mask but differing IP addresses in the 192.168.6.X range (192.168.6.6 , 192.168.6.7, etc)
I have an application running on the PC with multiple NIC adapters and it is binding and joining a multicast group to receive packets. The issue I am having is that the multicast packets that are being sent from one of the PCs in the system (i.e. 192.168.6.6) are not being received by my application. I can see the multicast packets in Wireshark when viewing either NIC's traffic so I believe that each NIC is getting the packets properly.
A small snippet:
{
IPEndPoint localIPEndPoint
localIPEndPoint = new IPEndPoint(IPAddress.Parse("192.168.6.1"), 16466);
receiveUDPClient = new UdpClient(localIPEndPoint);
receiveUDPClient.JoinMulticastGroup(IPAddress.Parse("239.254.2.1"));
receiveUDPClient.MulticastLoopback = false;
receiveUDPClient.DontFragment = true;
receiveUDPClient.Client.ReceiveBufferSize = 16384;
// ....
// ....
BeginReceiveAudio();
}
public void BeginReceiveAudio()
{
receiveUDPClient.BeginReceive(ReceiveCallback, receiveUDPClient);
}
I am processing the packets in a callback which I know works fine when using a single NIC -- in fact if I simply disable the 192.168.2.90 NIC adapter my application receives the packets just fine.
private void ReceiveCallback(IAsyncResult ar)
{
byte[] receivedBytes = receiveUDPClient.EndReceive(ar, ref localIPEndPoint);
// Process Data...
BeginReceiveAudio();
}
The other interesting thing is that if I swap the IP addresses of the adapter's while both enabled, my application receives the packets just fine! I am not at all familiar with how the packets get routed to each NIC; I assumed that when you bind to an IP Address and join a multicast group, any packets transmitted to that multicast group get received by the PC are routed to each NIC that is a part of that multicast group.
Any clue whats going on here? Given that it's one common network, what would be the reason that using one NIC lets my application recieve the packets but the other doesn't?
You need to join the multicast group via each available interface, so that the IGMP messages get sent out via each, so that the hosts on all those networks know there is a multicast member. If you only join once without specifying the interface, the static IP route is used to determine where the IGMP is sent, which is only one network.
The problem is you are using the line below and assuming that it is sufficient for using the correct NIC
receiveUDPClient = new UdpClient(localIPEndPoint);
The reality of the matter is that when you use that client to join the multicast address, the OS does not force the IGMP message to go out of that Endpoint. To force the IGMP out of the endpoint you desire, you need to use the two parameter method for joining the multicast address, where the second IP address is local enpoint you are wanting to listen on. Simply use the line below instead of the single parameter JoinMulticastGroup method:
receiveUDPClient.JoinMulticastGroup(IPAddress.Parse("239.254.2.1"), IPAddress.Parse("192.168.6.1"));
I wish that this wasn't necessary, since it would make sense for the all the JoinMulticastGroup methods to use the currently bound endpoint as the default localEndpoint, but it doesn't work that way.

Allow client app to automatically connect to server app on same network

I've created two apps (A client and a server) which can communicate with each other as long as I input the local IP address of the machine the server app is running on into the client app (in code).
I would like the client app to automatically discover the local IP address of the machine running the server app and connect to it, so they can be run on any network without the need to enter the IP in code.
Both of these apps with be running on the same network (ie. Over WiFi, not the Internet)
Here is what I have so far in my client app:
// COMMUNICATE WITH SERVER
private TcpClient client = new TcpClient();
private IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("192.168.2.35"), 8888);
public Console()
{
InitializeComponent();
client.Connect(serverEndPoint);
}
private void SendMessage(string msg)
{
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(msg);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
In this example I can only connect to a server running on "192.168.2.35", I would like it to be able to find the server running on port 8888 on any machine on the network.
Alternatively, if this isn't possible I would like the server to broadcast its IP as a message (of some sort) and have the client receive this message and verify it is the server and connect to it.
I think my second example is the proper way to do this, but I can't seem to wrap my head around how to get it working (I'm fairly new to C#), and any other examples I've found I can't seem to get to work with my applications.
Here is my server code if it helps answer my question:
private void Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 8888);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
TcpClient client = this.tcpListener.AcceptTcpClient();
connectedClients++;
lblNumberOfConnections.Text = connectedClients.ToString();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
Thanks
EDIT: I've tried adding THIS to my project, but being so new I'm unsure how to implement it properly, and it didn't get me anywhere.
2nd EDIT: I've tried implementing a UDP broadcast a few times now, with no luck on any attempt yet. My latest attempt was at implementing THIS (minus the chat parts). I just can't seem to get a UDP broadcast working at all with my project, as it seems to be way over my head at my current skill level. Unfortunately, having my client automatically connect to the server is 100% necessary for my project to function...
My other problem, which is maybe best to start a separate question for, but somewhat correlates to this issue is: My client GUI consists of a panel that switches between multiple custom classes, each containing different buttons, etc. (works similar to tab pages) that communicate to the server I'm trying to connect to. Once I get the UDP broadcast figured out, will I need to code that into every class separately? or is there a way of having all classes running in my panel connect to the same server?
A simple, but possibly costly(in terms of network traffic) solution would be for your server application to broadcast over UDP it's application and connection info. Your client could listen for all broadcast packets that have your servers custom header. Assuming a connection is made you could stop the broadcast. The downside is you would have to be broadcasting constantly if a client is not connected and this can clog your network if there aren't limits placed on the broadcast speed.
EDIT: Here is a boiled down explanation generated from the MSDN article https://msdn.microsoft.com/en-us/library/tst0kwb1(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
EDIT #2: I've expanded on this answer on my blog, as well as provided downloadable example projects. the article can be found at http://martialdeveloper.com/wordpress/?p=21
1. Find your network's broadcast IP
A special “Broadcast Address” must be used when using UDP for the purpose of sending a datagram to all machines connected to a given network. For example, the typical home network host/gateway of 192.168.0.1 has a broadcast address of 192.168.0.255. If your network differs from this you can use an IPv4 broadcast address calculator like the one found here http://jodies.de/ipcalc
Or read the introductory section on MSDN describing the broadcast address. https://msdn.microsoft.com/en-us/library/tst0kwb1(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
2. Select a listening/broadcast port
Any port that is free on your client & server is fine. The MSDN example uses 11000. This port number is used in your broadcaster, and listener.
3. Code for the Listener
Note to the reader. All error handling has been omitted for clarity of the example.
int listenPort = 11000;
bool done = false;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any,listenPort);
while (!done) // This loop listens for your broadcast packets
{
Console.WriteLine("Waiting for broadcast");
byte[] bytes = listener.Receive( ref groupEP);
Console.WriteLine("Received broadcast from {0} :\n {1}\n",
groupEP.ToString(),
Encoding.ASCII.GetString(bytes,0,bytes.Length));
}
listener.Close();
Note: The third parameter to Console.WriteLine, "Encoding.ASCII..." represents the string value sent over UDP in the datagram packet. This contains the desired negotiation information for a discovery situation, such as the IP address of the client or server you wish to connect to.
4. Code for the Broadcaster
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
IPAddress broadcast = IPAddress.Parse("This string should be the broadcast IP address"); //NOTE: Broadcast IP goes here!!
byte[] sendbuf = Encoding.ASCII.GetBytes("This is the message string to be broadcast"); //Your message to the client/server goes here, I.E. an
// app/client name or ID and an IP to connect with over TCP
IPEndPoint ep = new IPEndPoint(broadcast, 11000);
s.SendTo(sendbuf, ep);
Console.WriteLine("Message sent to the broadcast address");
NOTE: This is a very simple example. The broadcaster may need to rebroadcast for a period of time to make sure the Listener receives it. Even after the UDP datagram is sent/received there will need to be some negotiation to ensure the TCP connection is made properly.

C# Unable to receive WOL package with UdpClient

I'm trying to receive a WOL package within my C# application. I guess the problem why it doesn't work has something to do with how the package is broadcasted by my router running DD-WRT.
The code I use to receive an UDP package:
UdpClient udp = new UdpClient(10);
IPEndPoint all = new IPEndPoint(IPAddress.Any, 0);
while (true)
{
System.Diagnostics.Debug.Print("listening");
byte[] receivedBytes = udp.Receive(ref all);
System.Diagnostics.Debug.Print(Encoding.ASCII.GetString(receivedBytes));
}
This already worked with my old router but now I have DD-WRT running and it had to be setup like this:
I port-forward incoming UDP packages on Port 10 to the (non existing) IP 192.168.1.254
On startup of the router the command "arp -i br0 -s 192.168.1.254 FF:FF:FF:FF:FF:FF" is executed to broadcast the messages received on that IP.
This setup works, a magic package is received by every machine and I can wake them up from outside of my network.
WireShark is able to catch this packages but "udp.Receive(ref all);" is not. This is how a WOL package send to my router looks like in Wireshark:
http://i.stack.imgur.com/nxaAP.png
If I send (from within my C# application) a Broadcasted UDP MagicPackage on the other hand, this package is received by my code above. This MagicPackage shows up in Wireshark like this:
http://i.stack.imgur.com/tPU1v.png
So I'm not 100% sure if the different "Destination" (192.168.1.254 versus 255.255.255.255) or the different "Protocoll" (WOL versus UDP) is the problem. My guess is, that the UdpClient ignores the WOL package because it's destination (within the IP header) is a different IP address (the code is running on machine 192.168.1.2). The second package on the other hand has a destination address of "255.255.255.255" in its IP Header and is therefor catched by the UdpClient.
So the big question is: How do I set up an UDP listener that also receives the WOL package broadcasted by my router?
BTW: I also already tried it with this code but without any luck:
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
EndPoint iep = new IPEndPoint(IPAddress.Any, 10);
sock.Bind(iep);
byte[] data = new byte[1024];
int recv = sock.ReceiveFrom(data, ref iep);
Check this property:
http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.enablebroadcast.aspx
I believe WOL packets are broadcasted. In this case it should help.
EDIT:
After checking your Wireshark screenshot I think the issue is not in your code. As far as I know there are many filters in network stack. The first one is MAC filter. WOL packet will go throught because of broadcast address ff:ff:ff.... The second filter is on IP Address. Your WOL packet has destination IP ...1.254, but your OS is expecting ...1.2 and therefor the IP stack will throw this packet and your app will not receive anything. Wireshark on the other side switches the network card to "promiscuous mode" where all filters are turned off and wireshark is able to capture everything.
So to solve this:
1) You can implement similar behavior as Wireshark using some capture library - take a look at WinPCAP - http://www.winpcap.org/
2) Try to use RAW sockets, but I am not sure that this will work - http://en.wikipedia.org/wiki/Raw_socket
3) Best way would be to fix your router to send WOLs in standard format.

C# - WireShark detects incomming packets but application does not receive them

I've got a strange problem. I have a client sending packets to my server, but my servers UDP socket never receives them. Same thing happens the other way around, if I send and he tries to receive.
Check this image, captured from wireshark:
http://img263.imageshack.us/img263/2636/bokus.png
I hav bound my UDP socket to EndPoint 192.168.2.3, which is the internal IP of the server, and port 9998.
The client sends data to my IP, which should then be forwarded to the local server machine..
As you can see wireshark clearly detects incomming packets for 192.168.2.3 with destination port 9998 but nothing gets delivered!
(...why does it say distinct32 btw in destination port?)
Something else to watch for is make sure any firewall you might running has a rule setup to allow communications on your port 9998.
If I had to guess (would need to see your recieving C# code to know), It looks like you might be trying to receive UDP packets but using TCP protocol on the client side. (Or i might just be misunderstanding some of the text of your screenshot.)
Theres no need to 'listen' for a connection when using UDP. UDP packets don't have a connect/disconnect protocol. Nor do they guarantee that packets are received in the same order they're sent.
try using something along these lines in your C# client and see if you get data.
var udpClient = new System.Net.Sockets.UdpClient(9998);
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);

Categories