Click here to Skip to main content
15,886,689 members
Articles / Programming Languages / C#
Article

Observing Applications via Heartbeat

Rate me:
Please Sign up or sign in to vote.
4.02/5 (21 votes)
3 Oct 2004CPOL2 min read 115.8K   2.7K   51   14
A method to check if an application is working or has crashed.

Heartbeat with working and 'nonworking' Application

Introduction

Some time ago, in the C# Forum occurred the question how to check if an application is still running or has crashed. The only way to check if the application is running is to have another application that does this job. The application can not control itself, because 'a dead dog will not bark'.

Background

To check if an application is running, this application sends regularly an UDP packet, the heartbeat. The observing application listens for the heartbeat (the UDP Packets). If the heartbeat is missing for a certain period, we have to assume that our observed application has crashed. As this works with UDP packets, this supervision can work on the same machine, on another machine in the LAN, or even over the Internet.

Description of the Code

The code is really small and documented, so I will not write a big story about this code.

ClientForm

The ClientForm class represents the observed application. In the Eventhandler function of the Timer, the SendUdpPacket() function is called when the checkbox is checked (to simulate a working/non-working application).

C#
private void SendUdpPacket()
{
    byte[] data = new byte[1024];

    // Create UDP Socket
    Socket udpClientSocket = new Socket( AddressFamily.InterNetwork, 
                        SocketType.Dgram, 
                        ProtocolType.Udp);

    // Send Application Title (Window Title) as the Data
    data = Encoding.ASCII.GetBytes(this.Text);

    // Send it ...
    udpClientSocket.SendTo(data,0,data.Length,SocketFlags.None,ipep);
}

ServerForm

The ServerForm class represents the observing application. In the constructor, the Listening Socket and the Timer are initialized:

C#
public ServerForm()
{
    ...

    udpServerSocket = new Socket(AddressFamily.InterNetwork,
                          SocketType.Dgram, ProtocolType.Udp);
    udpServerSocket.Bind(ep);
    udpServerSocket.BeginReceiveFrom( buffer, 
                                      0, 
                                      1024, 
                                      SocketFlags.None, 
                                      ref ep, 
                                      new AsyncCallback(ReceiveData), 
                                      udpServerSocket);

    checkTimer.Interval = 1000;
    checkTimer.AutoReset = true;
    checkTimer.Elapsed += new 
              System.Timers.ElapsedEventHandler(checkTimer_Elapsed);
    checkTimer.Start();
}

The most important part of the callback function ReceiveData() is the updating of the timestamp lastUpdate.

C#
void ReceiveData(IAsyncResult iar)
{
    // Create temporary remote end Point
    IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
    EndPoint tempRemoteEP = (EndPoint)sender;

    // Get the Socket
    Socket remote = (Socket)iar.AsyncState;

    // Call EndReceiveFrom to get the received Data
    int recv = remote.EndReceiveFrom(iar, ref tempRemoteEP);

    // Get the Data from the buffer to a string
    string stringData = Encoding.ASCII.GetString(buffer,0,recv);
    Console.WriteLine(stringData);

    // update Timestamp
    lastUpdate = DateTime.Now.ToUniversalTime();

    // Restart receiving
    if(!this.IsDisposed)
    {
        udpServerSocket.BeginReceiveFrom( buffer, 
                            0, 
                            1024, 
                            SocketFlags.None, 
                            ref ep, 
                            new AsyncCallback(ReceiveData), 
                            udpServerSocket);
    }
}

In the EventHandler of the Timer, the time span since the last update of the timestamp lastUpdate is checked. If the time span is too big, the Label text and color are changed.

C#
private void checkTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    // Calculate the Timespan since the Last Update from the Client.
    TimeSpan timeSinceLastHeartbeat = DateTime.Now.ToUniversalTime() - lastUpdate;

    // Set Lable Text depending of the Timespan
    if(timeSinceLastHeartbeat > TimeSpan.FromSeconds(3))
    {
        lblError.Text = "No Answer from ClientForm";
        lblError.BackColor = Color.Red;
    }
    else
    {
        lblError.Text = "ClientForm OK";
        lblError.BackColor = Color.Green;
    }
}

Application 'in the Wild'

For a serious observing application, it should not just change the color or text of a label but send an email, send a SMS or paging message or something else. It would make sense to create a service for the observing application and to implement it so that it observes several different applications, maybe also on different machines.

The observed applications should send the heartbeat not from a thread only for this task but from the working thread, if this is possible. When the heartbeat is sent from a thread only for this task, you will not recognize if the important thread of your application has died or is blocked (maybe from a deadlock) because the heartbeat signal is still sent.

Conclusion

The given example was only one way to observe an application. There are other ways (like TCP Connection, Pipes etc.), but you need always another application to observe your application. You can build even more complex heartbeats, like sending a status, and you can use the same mechanism to send warnings and errors to your observing application. So your observing application can become your 'application supervision and alarm management central'.

History

  • Version 1.01, Posted 29. September 2004
    Made Observer 'daylight saving time'-save. Thanks to jbryner for his advice.

  • Version 1.00, Posted 22. September 2004
    Initial Version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Switzerland Switzerland
View more on www.rolandbaer.ch.

Comments and Discussions

 
QuestionGet an when trying to debug - Can't get around it. Pin
Norm Normal17-Nov-17 17:44
Norm Normal17-Nov-17 17:44 
I wish this would work.... Error is on line 38 ( udpServerSocket.Bind(ep); ) of the server:

System.Net.Sockets.SocketException occurred
HResult=0x80004005
Message=Only one usage of each socket address (protocol/network address/port) is normally permitted
Source=<cannot evaluate="" the="" exception="" source="">
StackTrace:
<cannot evaluate="" the="" exception="" stack="" trace="">

Thanks!
AnswerRe: Get an when trying to debug - Can't get around it. Pin
Roland Bär3-May-18 9:42
Roland Bär3-May-18 9:42 
QuestionHow can i do it in Asp.net web application Pin
demouser7433-Oct-11 2:04
demouser7433-Oct-11 2:04 
Questionis that work with 2 pc ? Pin
kenix1-Apr-08 23:44
kenix1-Apr-08 23:44 
AnswerRe: is that work with 2 pc ? Pin
Roland Bär3-Apr-08 4:35
Roland Bär3-Apr-08 4:35 
GeneralBuffer Problem Pin
Suganya Shanthini22-Mar-06 23:24
Suganya Shanthini22-Mar-06 23:24 
AnswerRe: Buffer Problem Pin
Roland Bär23-Mar-06 8:12
Roland Bär23-Mar-06 8:12 
QuestionCan also use WaitForSingleObject Pin
dcsoft6-Oct-04 7:52
dcsoft6-Oct-04 7:52 
QuestionSNMP? Pin
Simon Hughes28-Sep-04 11:47
Simon Hughes28-Sep-04 11:47 
AnswerRe: SNMP? Pin
Roland Bär29-Sep-04 10:05
Roland Bär29-Sep-04 10:05 
Generaltime changes Pin
jbryner28-Sep-04 7:46
jbryner28-Sep-04 7:46 
GeneralRe: time changes Pin
Roland Bär29-Sep-04 8:35
Roland Bär29-Sep-04 8:35 
GeneralEffort Pin
sreejith ss nair21-Sep-04 22:10
sreejith ss nair21-Sep-04 22:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.