Receiving UDP messages using UdpClient or Socket classes

Last week I started work on a logging tool for Half-Life based games. You can read more about it on this blog.

Anyway, as part of this tool I need to receive UDP datagram packets over a network connection. There is a .NET Framework class called UdpClient that does what you need. It’s the getting it to work that wasn’t too trivial (at least to me). Here’s a code fragment that receives UDP packets:

using System.Text;
using System.Net;

int port = Int32.Parse(ConfigurationSettings.AppSettings[listenPort]);
UdpClient client =
new UdpClient(port);
int
bufferSize = 1024;
buffer =
new
Byte[bufferSize];
IPEndPoint ep =
new IPEndPoint(IPAddress.Any, port);

while (true)
{
  buffer = client.Receive(
ref
ep);
  string
message = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
  Debug.WriteLine(ep.Address.ToString() + “: ” + message);
}

The tricky bits here are invisible. I tried to use the UdpClient::Connect method, which will make the whole thing not working.

The Receive call blocks until actual data is received. No need to worry about the infinite loop and processor load for that. I spawn this loop on a new background thread, so it will die automatically when the main thread of the application stops. You might want to use a more controllable mechanism to abort this thread gracefully.

In my quest to get things working I found a way to accomplish the same result with a raw socket using the Socket class. The approach is a bit different, as it uses a delegate to trigger the receival of data. Here’s how it goes:

private Byte[] buffer;

public void StartListening()
{
  int
port = Int32.Parse(ConfigurationSettings.AppSettings[listenPort]);
  int
bufferSize = 1024;
  buffer =
new
Byte[bufferSize];
  IPEndPoint ep =
new
IPEndPoint(IPAddress.Any, port);
  Socket sock =
new
Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  sock.Bind(ep);
  sock.BeginReceive(buffer, 0, 1024, SocketFlags.None,
new AsyncCallback(this
.OnReceive), sock);
}

private void OnReceive(IAsyncResult ar)
{
  Socket s1 = (Socket)ar.AsyncState;
  int
x = s1.EndReceive(ar);
  string
message = System.Text.Encoding.ASCII.GetString(buffer, 0, x);
  Console.WriteLine(message);
  s1.BeginReceive(buffer, 0, 1024, SocketFlags.None, new AsyncCallback(this
.OnReceive), s1);
}

In StartListening an asynchronous receive is started. This call will not block until data is received, but continue straight away, ending the secondary thread on which the StartListening was started. Because of the asynchronous call, a thread from the .NET runtime’s thread pool will be used to do a callback on OnReceive once actual UDP data is delivered to the port through the AsyncCallback delegate. OnReceive in turn triggers another asynchronous receive, starting the whole thing over again. In effect, the background thread keeps itself alive (although different threads from the pool might be used).

Hope this helps you if you happen to stumble onto this.

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s