Jarloo

Menu

C# UDP Multicasting Tutorial

Learn how to use a UDP Multicast in c# to quickly send data from one machine to a next. This method is commonly refered to as a UDP rendezvous.(yes probably why Tibco’s product that does this is called rendezvous)

This tutorial will consist of two programs:

  • Server (Sender) – a console app that is responsible for sending messages
  • Client (Listener) – a console app that is responsible for recieving messages

The reason they are both console apps is to keep things simple.

UDP Multicasting 101

Before we jump into the code there are a few things that you need to know.

Technically multicasting addresses must be between 224.0.0.0 to 239.255.255.255, but 224.0.0.0 to 224.0.0.255 is reserved for routing info so you should really only use 224.0.1.0 to 239.255.255.255.

For the port number you can choose anything you like but it’s best do investigate the port you choose a bit so you don’t conflict with something already using that port. A good place to look is wikipedia

UDP Multicasting C# Server (Sender)

The server must make a connection to our multicast address and then join our multicast group. By joining the group we can add content to it, which gets delivered to anyone else in the group.

IPAddress multicastaddress = IPAddress.Parse("239.0.0.222");
udpclient.JoinMulticastGroup(multicastaddress);
IPEndPoint remoteep = new IPEndPoint(multicastaddress, 2222);

Really that is it. The rest is just to encode the message and send it like so:

Byte[] buffer = null;
for (int i = 0; i <= 8000; i++)
{
	buffer = Encoding.Unicode.GetBytes(i.ToString());
	udpclient.Send(buffer, buffer.Length, remoteep);
}
&#91;/csharp&#93;

Now because this is a Console app we can add a new messages in there to see whats going on. The complete class looks like this:

&#91;csharp&#93;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Jarloo.Sender
{
    internal class Program
    {
        private static void Main(string&#91;&#93; args)
        {
            UdpClient udpclient = new UdpClient();

            IPAddress multicastaddress = IPAddress.Parse("239.0.0.222");
            udpclient.JoinMulticastGroup(multicastaddress);
            IPEndPoint remoteep = new IPEndPoint(multicastaddress, 2222);

            Byte&#91;&#93; buffer = null;

            Console.WriteLine("Press ENTER to start sending messages");
            Console.ReadLine();

            for (int i = 0; i <= 8000; i++)
            {
                buffer = Encoding.Unicode.GetBytes(i.ToString());
                udpclient.Send(buffer, buffer.Length, remoteep);
                Console.WriteLine("Sent " + i);
            }

            Console.WriteLine("All Done! Press ENTER to quit.");
            Console.ReadLine();
        }
    }
}
&#91;/csharp&#93;

<h2>UDP Multicasting C# Client (Listener)</h2>
Like the server the client must also connect to the multicast group


UdpClient client = new UdpClient();

IPEndPoint localEp = new IPEndPoint(IPAddress.Any, 2222);
client.Client.Bind(localEp);

IPAddress multicastaddress = IPAddress.Parse("239.0.0.222");
client.JoinMulticastGroup(multicastaddress);

Notice the code looks very similiar to the sender we created except that we bind to an endpoint. This is necessary as we will be listening for incoming data.

So now that were connected we just need to listen for messages and do something with them.

while (true)
{
	Byte[] data = client.Receive(ref remote);
	string strData = Encoding.Unicode.GetString(data);
	Console.WriteLine(strData);
}

Yes that is an infinate loop. (this is just for demonstration purposes remember?) To close this client down you will have to kill it. Yes there are easier ways including sending a quit message from the server etc.. etc.., but I didn’t want to add a bunch of code that would confuse things here.
Also important to note is that the client.Receive call is blocking. This means that code execution will halt on that line until a message is received. So if you do something similiar in your own programs you would either want this on a different thread or you would want to use the async methods instead. (Async methods are best because if you multi-thread it, to stop the client you will need to interrupt the thread which will throw an exception.)

One issue you’ll discover is that you can only have a single listener working on a machine at a time. This is because the port is set for exclusive use. So if you want multiple Listeners on a single machine you will need to change this by doing this:

client.ExclusiveAddressUse = false;
IPEndPoint localEp = new IPEndPoint(IPAddress.Any, 2222);

client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.ExclusiveAddressUse = false;

This would go right under the creation of the UdpClient.

The complete code the Listener looks like this:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Jarloo.Listener
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            UdpClient client = new UdpClient();

            client.ExclusiveAddressUse = false;
            IPEndPoint localEp = new IPEndPoint(IPAddress.Any, 2222);

            client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            client.ExclusiveAddressUse = false;

            client.Client.Bind(localEp);

            IPAddress multicastaddress = IPAddress.Parse("239.0.0.222");
            client.JoinMulticastGroup(multicastaddress);

            Console.WriteLine("Listening this will never quit so you will need to ctrl-c it");

            while (true)
            {
                Byte[] data = client.Receive(ref localEp);
                string strData = Encoding.Unicode.GetString(data);
                Console.WriteLine(strData);
            }
        }
    }
}

Summary

UDP Multicasting is a great way to send around data but there are a few things to look at to determine if this method is right for you.

Pros

  • Requires no dedicated server. Your client and server can be the same app, making this a very nice distributed solution with no single point of failure.
  • Fast. Very, very fast. Since there are no extra jumps to servers and translation etc the code executes very fast.

Cons

  • Messages are not guaranteed. They can be lost, so if your passing around something critical like banking transactions this wouldn’t be a good idea.

Common uses for this style of architecture are in places where data is updating very quickly and each message sent has a very short lifespan. You see this being used in trading shops quite a bit for sending prices. If a single price is lost, it’s not that big of a deal because another one will follow in seconds.

Alternatives

If your looking to route data to multiple machines the problem has been tackled before, and there are some great open source projects that work very well and can help. Two I would recommend are:

  • RabbitMQ – This is the easiest setup for a queuing system I have seen, and it once you get it up and running it just works without issue. I’ve been using this in a production scenario for over a year and am very happy with it. Used to use ActiveMQ but I’ve found this much better and more reliable.
    I have a RabbitMQ Tutorial if your interested.
  • ZeroMQ – This one I haven’t personally used yet, but it sounds very good and it created to be extremely low latency.

Hope you enjoyed this tutorial, if I get the time I’ll post an Async version of this.

Categories:   Code

Tags:  , ,

Comments

Sorry, comments are closed for this item.