Sunday, March 14, 2010

Listening for UDP packets in a Windows service using an UdpClient

In this post, I'll show you how can you listen for UDP packets in a Windows service.


When the service starts, I set the started flag to true, initialize the ManualResetEvent, initialize an UdpClient and a WorkingThread. The ManualResetEvent will help us on a later stage to make our service stop elegantly.

   1:  protected override void OnStart(string[] args)
   2:  {
   3:       Start();
   4:  }
   6:  public void Start()
   7:  {
   8:       m_started = true;
  10:       m_stop = new ManualResetEvent(false);
  12:       InitializeUdpListener();
  13:       InitializeWorkingThread();
  14:  }


First we need to initialize an IPEndpoint. When the IPEndpoint is initialized we can initialize the UdpClient using that IPEndpoint.

   1:  private void InitializeUdpClient()
   2:  {
   3:       m_endPoint = new IPEndPoint(IPAddress.Any, PORT_NUMBER);            
   4:       m_client = new UdpClient(m_endPoint);
   5:  }

After initializing our UdpClient, we can initialize and start the WorkingThread.

   1:  private void InitializeWorkingThread()
   2:  {
   3:       m_workingThread = new Thread(WorkerFunction);
   4:       m_workingThread.Name = "WorkingThread";
   5:       m_workingThread.Start();
   6:  }


The WorkerFunction does all the work.

While the service is started, we start receiving packets. We pass in an AsyncCallback Delegate which is called when the asynchronous operation completes. In this delegate we make sure that the result we receive is complete. If the result is complete we end receiving and get the content of the UDP packet.

Finally we use the WaitHandle to wait for either the asynchronous operation to complete or the workerthread to grant a termination request through the stop ManualResetEvent.

   1:  private void WorkerFunction()
   2:  {
   3:       while (m_started)
   4:       {
   5:           //BeginReceive starts an asynchronous operation, in reality to allow us to achieve
   6:           //semi-synchronous invocation, where we wait for either the asynchronous operation
   7:           //to complete or the worker thread to grant a termination request through stop
   8:           var res = m_client.BeginReceive(iar =>
   9:           {
  10:                if (iar.IsCompleted)
  11:                {
  12:                     byte[] receivedBytes = m_client.EndReceive(iar, ref m_endPoint);
  13:                     string receivedPacket = Encoding.ASCII.GetString(receivedBytes);
  14:                }
  15:            }, null);
  17:            if (WaitHandle.WaitAny(new[] { m_stop, res.AsyncWaitHandle }) == 0)
  18:            {
  19:                break;
  20:            }
  21:       }
  22:  }        


In the OnStop event we need to set the ManualResetEvent, so our WorkerFunction can exit gracefully.

   1:  protected override void OnStop()
   2:  {
   3:      m_stop.Set();
   4:      m_started = false;
   5:  }

I'm pretty sure this is a robust solution. A service based on this example deployed to production has been handling 1000 packets an hour on average for the last three weeks without problems.

Thanks to Bart De Smet for helping me out with the threading stuff!


  1. The source cannot be downloaded anymore because of a Rapidshare error, could you rehost it so you can share your genius with the world? :)

  2. I reuploaded the source! I changed the link in the post.

  3. This comment has been removed by the author.

  4. Source cant be downloaded again, because Rapidshare download limit reached.

  5. I'm sorry. I reuploaded the source ( I had to redo it because I lost the original source myself.

  6. Is the source code referenced in this article still available?

    1. Sorry, this was a looong time ago. I removed the broken link.

  7. Thanks for the reply. I was able to piece together a working sample from the code shown in the article. I am now working on sending a reply to the sender of the incoming message and was looking for assistance.

    1. To be fair, if I had to do something like this today, I might rather look at something like 0MQ.

  8. Based on your original sample, I was able to extend the UDP listener service so that it sends a response (reply) to the sender. This allows us to communicate with hardware devices manufactured by a business partner of ours that specifically use UDP. I will, however, also look into 0MQ. Thanks again for responding to this rather old thread!

    1. No problem! Happy to know some people still find the old stuff useful ;-)