Smart CODE
Your on-line guide to the generated code

Server Push/Automatic Update. A worked example


Introduction

The application we use for this example is almost the same as for the previous one. After all, the interface is a thin client, whose behaviour is governed by the server it talks to.

We are going to write an application that updates its data display in real time, or at least at regular intervals. This is now a common feature on the Internet, where web pages update their content as and when it needs to be changed.

The example will be trivial, as it is a demonstration that requires no special knowledge. The server will update a clock in the client at regular intervals.

Things you must do/know BEFORE running the example

Environment Variables etc

As always, you should make sure that $XDROOT/bin is in your path.

Here is a summary of the variables you will need to set up before working through the example

XDROOT
LM_LICENSE_FILE

Preparing the Example

Step 1 Create a new directory called, for example, timex
Step 2 Change directory to timex
Step 3 Run xdesigner using the xdreplay script $XDROOT/src/examples/sc/timex.vcr, ie

$ xdreplay -f $XDROOT/src/examples/sc/timex.vcr xdesigner


This will create the example application, generate the code, copy standard versions of the callbacks you would have written into the appropriate place, and invoke make to build the program.

Running the Example

First, check that you have set up the environment variables. If there is a problem, check that they are set correctly, eg

$ ls $XDROOT

You run the example application by typing

$ ./untitled

All you have to do to run the program is press the button. This triggers the callback, which connects back to the server. The current time (at least for the local timezone on the server where the program is running) is displayed in the text field. However, your program will poll the server as often as is required, and will update the time in the text field.

Some words of explanation

The only difference between this and the previous example, is that on the Thin Client Properties page, you should press the Server Push toggle.

If you are going to use our prebuilt version, you should use the URL:


http://www.ist.co.uk/cgi-bin/xd5_timex

As an alternative to configuring the Proxy and Port fields, you can set the environment variable HTTP_PROXY, eg

	% setenv HTTP_PROXY     meinhost:80

Traditionally, web pages update via a refresh mechanism. In other words the data isn't being pushed from the server at all, but the client is polling the server regularly for an update. This was because the original implementation did not allow persistent connections between a server and its clients. The connection was maintained only for the duration of the data transfer. More recent developments have allowed for persistent connections, but while this is not yet the dominant paradigm, we have implemented our asynchronous update in the traditional way, as the client polling the server.

With HTML, the server controls the refresh rate, and the same is true here. The server knows how frequently the data updates, and when it is worth polling for an update.

In the example callback below, which runs in the server, the poll interval is set by the line


data->poll = 10; /* retry every ten seconds */

As long as the poll value is a positive non-zero value, the client will continue to poll the server and update its interface.

The example uses two very simple system calls to write the current time to the interface's text field. It is only an illustration, but it will allow you to put together a first-time self-updating application very quickly.

time() gets the current time as a number (the number of seconds since 1 Jan 1970), and ctime() converts this number into a string.

You must pass the address of the time (&t) to both functions for them to work properly.


#include <time.h>

int
doit_callback  ( sc_data_t * data)
{
	group0_t * g = (group0_t*)data->group;

	time_t t;

	data->poll = 10; /* retry every ten seconds */

	time( &t);

	SC_SET(g->text1,ctime(&t));

	return 1;
}

Notes