January 4, 2008

The wonderful world of UDP Broadcasts

I have been working on a set of server/client applications lately. Basically, the server and client communicate via TCP. This means you need to provide an IP address and port number that the server is on so that the client can connect to it. The problem is that many users do not understand what an IP address is, much less how to find one; all hope is lost, then, if they must supply a port as well. The port problem is somewhat resolved in that the port number is typically fixed. No mater what machine the server is on, it will always communicate on say, port 4040. This will only be a problem if another application on the same machine is also attempting to use port 4040. The more complex issue to try to get around is obtaining the IP address. Every machine will have a different IP address, and even then it may change every time you enable its network device.

Now assuming that your server and client will be on two machines that are very close to one another (not spanning across the internet), there is a nice way to build into your server and client that will help the client 'magically' figure out the server's IP address. The answer lies with UDP broadcasts. UDP is similar to TCP in that they both require an IP address and a port number. The beauty of UDP is that it allow something called a broadcast. A broadcast will allow you to send information to a certain port, but to every computer on your network. If there is an application listening on that port on any computer on the network, it will be able to receive the information. There is also a Time To Live (TTL) associated with the UDP broadcast which says how many routers deep the transmission is to go.

The way we will work our 'magic' is by having our client broadcast a message via UDP broadcast to a port that our server will be listening on. Once the server receive the information, it automatically gets the IP address of the client along with it. Once we have the client's IP address, we can send that client a UDP message on a port that it will be listening on to the IP that we obtained. Once the client receives that message, guess what, we now automatically get the IP address of the server. Now that we have the IP address of the server, we can connect to our server via TCP to the port that it is listening on.

Here is an idea of what some of the code may look like.

The following segment of code shows how we can open a UDP socket to listen for any incoming messages on port 4040.



using System.Net;
using System.Net.Sockets;

...

IPEndPoint endpoint = null;
int port = 4040;
UdpClient listener = new UdpClient(port);

byte[] receivedData = listener.Receive(endpoint);

IPAddress addressOfSender = endpoint.Address;



The following segment of code shows how we can open a UDP socket to broadcast a message on port 4040 to all network computers.

using System.Net;
using System.Net.Sockets;

...

int port = 4040;

//IPAddress.Broadcast can be replaced with a specific IP here if we do not want to broadcast to everyone
IPEndPoint broadcastEndpoint = new IPEndPoint(IPAddress.Broadcast, port);
UdpClient broadcaster = new UdpClient();

byte[] broadcastData = /* assign some data do broadcastData */;

broadcaster.Send(broadcastData, broadcastData.Length, broadcastEndpoint);


I have implemented the UDP broadcast mechanism that I have mentioned above into my projects. The result is that now I can put my client and server on any two computers on the network, and they will automatically start communicating with one another without having the user supply an IP address or a port. It is often suggested that if you use this method that you still provide a way to allow the user to manually supply the IP and port in the event that UDP transmission are blocked on some firewall or router. It is also likely that you will want to modify the above code to use asynchronous sends and receives by replacing listener.Receive with listener.BeginReceive and broadcaster.Send with broadcaster.BeginSend. There is, of course, a bit of other code that will be needed to implement asynchronous transmissions, but that is beyond the scope of this article. Happy broadcasting!

No comments: