Question

Okay, this is my first stack overflow question so please feel free to suggest better ways to ask or what I should include next time. Most of the time I can Google to get my answers but this one is a little trickier...

I am writing a windows application in C# that listens on a UDP port and then process the incoming UDP messages. More specifically, I am using the UDPClient class and listening using the BeginReceive method. The receive callback is in turn firing it's own message received event and then resetting the UDP client again. This "MessageReceived" event is subsequently handled by a processor object.

I thought that was all pretty smart until my manager posed some questions to me such as:

  • How many messages can this receive at one time? What happens if we get more than that?
  • Are the messages queued or will they be lost if processing takes too long?
  • What does happen if the processing takes too long?

We cannot be losing the messages because the last one was still processing, and we can't be building up until the system crashes because it's out of memory either. What he would like to hear (and rightfully so) is some sort of verification that there is a deterministic way to deal with a "storm" of messages. Unfortunately, I have no idea where to go with this to get an answer. I have included what I think is the relevant code below.

So:

  1. Does anyone know the answers to the questions above?
  2. Where would I do some research to find these answers and/or some patterns to follow for this sort of thing?
  3. What kind of tools could I use to watch the processing for debugging/performance profiling?
  4. If I have made a huge mistake in my design, what should I do to sort it out (i.e. introduce a queue, use a thread pool etc)?

    public void ReceiveCallback(IAsyncResult ar)
    {
        //Cast the item back to the listener
        UdpListener listener = (UdpListener)ar.AsyncState;
    
        //If we are supposed to be listening, then get the data from the socket
        //Listen is false during shutdown
        if (Listen)
        {
            //The try catch is placed inside the listen loop so that if there is an error in the processing it will 
            //recover and listen again. this may cause more exceptions but we can be sure that it will not
            // stop listening without us knowing
            try
            {
                //Address and port from the external system
                IPEndPoint ep = listener.EndPoint;
    
                //Get the data from the async read
                Byte[] receiveBytes = listener.Client.EndReceive(ar, ref ep);
    
                //Reset the socket to listen again
                listener.Client.BeginReceive(new AsyncCallback(ReceiveCallback), listener);
    
                //Execute the event to pass external components the message
                HeartbeatEventArgs hea = new HeartbeatEventArgs(DateTime.Now, ep, receiveBytes);
                OnHeartbeatReceived(hea);
    
                //Ack back to the external system
                HeartbeatAcknowledgement(new IPEndPoint(ep.Address, ep.Port), receiveBytes);
            }
            catch (Exception e)
            {
                log.Error(e.Message);
                //Reset the socket to listen again
    
            }
        }
    }
    

listner is just a wrapper around UDPClient. As follows:

#region UdpClient Wrapper (UdpListener)
/// <summary>
/// UdpListener is used to control the asynchronous processing of a UDPClient object. 
/// </summary>
public class UdpListener
{
    /// <summary>
    /// IPEndpoint on which to accept a connection. Usually set to "Any".
    /// </summary>
    public IPEndPoint EndPoint { get; set; }
    /// <summary>
    /// The socket based client object that is used for communication
    /// </summary>
    public UdpClient Client { get; set; }

    public UdpListener(int port)
    {
        EndPoint = new IPEndPoint(IPAddress.Any, port);
        Client = new UdpClient(EndPoint);
    }
}
#endregion

Thanks,

Dinsdale

Was it helpful?

Solution

If losing messages is a concern, then UDP isn't for you. UDP guarantees only that if the message arrives, it will be complete. It does not guarantee message order or delivery. In other words, if a client sends two messages, you might receive them out of order, or only the first, or only the last (or none at all). If you need to guarantee delivery and order, use TCP instead (TCP comes with it's own set of guarantees and gotchas).

With regard how many messages it can process, you will have an upper limit. If you aren't processing messages faster than they are arriving, then they will be queued, either in your application layer or in the UDP networking layer. Once the network buffers are full, your network interface will simply begin throwing away messages.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top