Chapter 14

How Server Push Improves PlainChat


CONTENTS


The PlainChat application demonstrates how to build a Web chat environment. There are limitations to PlainChat, namely the need for users to constantly reload the Transcript page manually whenever they want to see what's "new."

This chapter is about Server Push and how adding it to the PlainChat application drastically improves the performance of the interface. The user is no longer required to reload the page manually because the Transcript page is automatically reloaded with Server Push.

Introduction to Server Push

Server Push technology is a relatively new addition to the feature set of Web servers and browsers. Today, several Web browser vendors support Server Push because the technology gives the Webmaster the versatility to create stunning pages and make effective use of the Web.

Server Push technology is used when different pages are to be loaded in sequence and pushed or sent from the server to the browser at intervals defined by the initial declaration to "push" pages.

A generic Server Push application follows to illustrate how this works. First, you need an HTML page to start things going. This example uses Server Push to count down to one from a number the user chooses (see Fig. 14.1) The user picks a number from the list presented and then clicks Start.

Figure 14.1: This is the entry page for the server pushed sequence of pages. This HTML page asks the user for information on how many times to go through the cycle (the cycle of pages pushed by the CGI script).

When the user selects a number, and starts the Server Push, the following CGI script is executed. The CGI script sends out a special MIME type declaration to the browser, instructing it to load each page in sequence as the program dictated.

Listing 14.1 shows you the HTML page to start the counting.


Listing 14.1  BasicPush.html-Basic Server Push Example Entry Page

<HTML>
<TITLE>Basic Push</TITLE>
<BODY BGCOLOR=ffffff>
<H1>Basic Server Push</H1>

<BODY>


<form action="/cgi-bin/basicpush.cgi">

How many pages do you want pushed?<br>
<input type="radio" name="howMany" value=4 checked>4
<input type="radio" name="howMany" value=6>6
<input type="radio" name="howMany" value=10>10
<p>

<input type="submit" value="Start">
</form>
<p>

<a href="index.html">Back</a>
</body>
</html>

The CGI script responsible for doing the Server Push is in Listing 14.2.


Listing 14.2  PushedChat.cgi-Implements the Server Push'd Pages

#!/usr/local/bin/perl

@INC = ('../lib',@INC);
require 'web.pl';

%Form = &getStdin;

$url = "http://$ThisHost:$ThisPort/ch14/";
$Marker = "-Marker-";

$|=1;
print  "HTTP/1.0 200\n",
       "Content-type: ",
       "multipart/x-mixed-replace;",
       "boundary=$Marker\n\n",
       "$Marker\n";
 while($Form{'howMany'}>0) {

    print "Content-type: text/html\n\n",
          "<title>Basic Push</title>\n",
          "<body bgcolor=ffffff>\n",
          "<h1>$Form{'howMany'}</h1>";
           if ($Form{'howMany'}==1) {
             print "<a href=\"$url\">done</a>\n";
        }
   print '                                         ' x 300, "\n",
         "$Marker\n";
   sleep 1;
   $Form{'howMany'}--;
 }

Let's walk through the steps to see how Server Push works. A user goes to a URL such as: http://www.mcp.com:9888/ch14/basic-push.html. In your example, you start at an HTML page and pick a countdown start value. This HTML page is a small HTML form.

As soon as the Start button is clicked, the CGI script defined as the ACTION for the form is invoked. The preceding Perl script is the code used if you go to the earlier URL.

The number to start counting from is stored in the form variable

$Form{'howMany'}

CGI programming's purpose is to generate pages. Usually, these pages are in HTML. In this example, the pages are indeed HTML, but you could push any kind of document type if you changed the MIME type sent to the browser:

print "Content-type: text/html\n\n";

This MIME type instructs the browser that what follows is HTML.

This CGI script starts a loop and continues generating an HTML page until the count is over. When the end of the countdown is reached, the script prints the HTML to put a link back to the entry form.

That's all there is to Server Push. But there are a lot of interesting things you can do with it, especially when it comes to Web chat environments.

The CGI script driving the "pushing" of pages sets the tempo of how often pages are sent to the client. Because a CGI script is driving the server push, there is really no limit to the kind of effect you can produce by using Server Push. For example, the Web chat is a great example of how Server Push can be used to improve the effectiveness of the chat application. Take the case you saw in the PlainChat application: A transcript page was generated every time the user either clicked the transmit or refresh button. Otherwise, she had to wait and manually refresh the page to see if any new messages were available.

PushedChat and Server Push

As you saw in Chapter 13, "What to Know About Live Communication," PlainChat forces the users to use the Reload button when they want to see new messages. With Server Push technology, our chat application doesn't force the user to use the Reload button. The goal for the PushedChat application is to improve PlainChat and utilize Server Push technology for the following reasons:

PushedChat is an application that utilizes Server Push. There are three pages to the PushedChat environment:

The PushedChat login page is the gateway to the environment. It's much like the other "chat login" page that you use with PlainChat. Then there is a "read-only" transcript page and a "read-write" transcript page. The difference is the default transcript page (the one that is automatically reloaded with Server Push) is read-only: You cannot type in new messages while viewing the read-only page.

A PushedChat environment is better for an interactive chat environment than PlainChat. The "interactivity" of the environment is focused on the content of the chat transcript instead of having the user manually reload the transcript page.

The main characteristic of a Server Pushed environment is that there is no need to force a user to reload the page. Further, it is an environment where you want to constantly refresh the page for the user for any number of reasons. For example, let's say a site is putting up the current ranking of the top ten runners of the women's marathon. At a reasonable interval, the page generating the current standings can be updated and pushed back to the client as the race progresses. It's not nessessarily real-time because there is an assumed time delay between each page being pushed. Pages shouldn't be pushed immediately after one another. The client would not have a fair chance to read the text, plus the flicker on some browsers would make the whole experience unattractive.

The choice to make when setting up a Server Pushed series of pages is to determine the expected size of each page you want to push. The size of each page, in terms of how many screenfuls necessary to show all the information, is an important consideration. If a user has to scroll down a considerable number of lines to get to some meaningful information, that time to scan and scroll is different for each user. There is a possibility that the user will be in the midst of reading that item most interesting to her and suddenly the page reloads automatically with updated information. Unless the Server Pushed environment is built to focus on just "adding to the top," and not completely revising the information completely this shouldn't happen too often. The Web chat that utilizes Server Push is a good application for Server Push because typically, the transcript page doesn't change except for the addition of another message (or more) each interval of time.

For the PushedChat environment the layout of the transcript page is also different than the PlainChat. First, there isn't a Reload button. In fact, there aren't any text areas or buttons to do anything except read the transcript. All the transcript log page does is give an up-to-date summary of all the current messages posted; the messages are updated as new ones are posted. How then does anyone contribute to the session?

The transcript page in the PushedChat environment is split into two logical pages. The first page is considered the read-only page; this is the page that just shows the current transcript log. No user input devices exist on the read-only page (see Fig. 14.2).

Figure 14.2: The read-only transcript page from the PushedChat environment doesn't have a text-area to type in; instead it uses a link to a read-write version of the transcript page.

When the user is visiting the PushedChat environment, the default page he sees is the transcript log page with no user input areas. The content of the default transcript page is only the messages, usually sorted by age from newest to oldest.

To contribute to the PushedChat environment, we need a page that has the familiar text areas and submit buttons to process the new messages. This is called the read-write page because the layout of this page has both devices for users to make comments and a section with a static view of the message log. After a user makes a new message and posts it, he is pushed back to the read-only transcript page. It's a two-page cycle: The cycle between the read-only (viewing) page and the read-write (updating) page. The user clicks the "talk now" link to get to the read-write page. The user clicks the "transmit" button to get to the read-only page.

To get from the read-only page, you program the PushedChat application software to place a hypertext link (a link of any kind, so long as it's an <"a href"> tag) to the read-write transcript page. There isn't any need to navigate from the read-write transcript page back to the read-only Server Pushed page, the CGI script does this automatically.

Navigation of PushedChat

The main point of the PushedChat application is to "remove as many unnecessary mouse clicks and navigation decisions from the user as possible." Another way to look at the interaction between the read-only (default) transcript page and read-write (user input) transcript page is that you assume that there is a larger set of users who are busy reading and fewer users who are busy writing. The frequency of new posts made to the transcript log will seem higher because as in more basic chat environments, there is a more immediate response to new messages. Web users want immediate gratification. Users who have to continuously reload the page are going to get tired of manually invoking the software to "update me" with the latest transcript page. They will just leave. On the other hand, with a PushedChat environment, the users don't need to exert any effort to participate in the environment.

When users are just lurking and watching what is happening in the PushedChat environment they are not locking themselves out of contributing. At any time, the user can click the "I want to talk" link to get to the read-write (user input) version of the transcript log page. The PushedChat helps influence users to "talk less and listen more" because as soon as they make their new messages and transmit them, they are pushed right back to the read-only transcript log page. You don't expect a user to post a new message and continuously do so without any respect for the others in the environment.

For example, in the PlainChat environment, it's possible for a user to just keep posting new messages without any regard because you are displaying a text area for him to type in every time he sees the transcript log.

We've discussed at length the difference between PushedChat and other chat systems described so far. The PushedChat uses Server Push to keep the flow of the environment steady and more realistic.

The PushedChat Application

The PushedChat application has a few components that are similar to the PlainChat application (the login page and read-write transcript log page). The new component to PushedChat with respect to the other chat systems is the read-only transcript page. This read-only transcript page is the only page that is generated using Server Push.

As a review, a login page in HTML looks something Listing 14.3.


Listing 14.3  PlainChat-Login.html-The Login Page for the PlainChat Environment

<HTML>
<TITLE>Login Page for PushedChat</TITLE>
<BODY BGCOLOR=FFFFFF>
<H1>Login Page for PushedChat</H1>
<P>
Please enter your name below:<BR>
(Example: Pat Smith)<BR>
<FORM METHOD=POST ACTION="/cgi-bin/pushedchat.cgi">

<INPUT NAME="theUsername"><BR>

Please enter your E-mail address below:<BR>
(Example: pat@some.place.com)<BR>
<INPUT NAME="theEmail">
<P>

<INPUT TYPE=SUBMIT VALUE="Enter PushedChat">
</FORM>

</BODY>
</HTML>

You're not ready to get into improvements to the content with PushedChat. You're using a similar login page because the improvements made by PushedChat are not in content, but in how well the chat environment runs compared to the PlainChat environment.

The CGI script driving the PushedChat environment is quite different from the PlainChat application in terms of how well the environment responds to the users. The PushedChat environment is highly interactive since the "interaction" is not strictly one-sided-the user doesn't have to nudge the session along by reloading by hand. The session just unfolds automatically for the user of the PushedChat environment.

The PushedChat environment is a sequence of pages that automatically refresh with a current view of the messages posted at any given time.

Caution
The function of the CGI script to do this is much like the functions in PlainChat. You just need to read in the transcript log file and display it. It's advisable to present the messages in the transcript log in reverse order with the most recent message on top. If the size of the transcript log grows faster than the CGI script is capable of handling at any moment, then you want to give the user a chance to read the messages that are most relevant.

We will cover ways to deal with extremely long log files with Server Push in later sections of this chapter. Basically, you'll handle it the same as with the high volume chat environment by putting links to "more" messages. The archives of messages shouldn't be Server Pushed.

In addition to the block of messages that are culled from the log file, the CGI script needs to generate a link in the page for a user to use as an "outlet" to speak up and contribute to the environment. On the read-only transcript page, the transcript of the chat log is refreshed for the user every interval. For the user to contribute, he has to click on the "speak now" link. This is preferred over the text-area placed in the transcript page because when the page refreshes, it will obliterate the message typed into the text area.

The logic of the CGI script for the PushedChat application that does the Server Push is an infinite loop. The script goes through the same steps of any chat, but continuously. The script reads in the transcript log, formats it, and dumps it to the browser with the proper HTML tags to format the user's name, the time of the message, and the message body. Inside the loop it does a few other things as well. It has to create a link to the read-write transcript page. It also has to do some waiting. The delay between each page reloading is set in the script. The script may also have to do some extra work to overfill the buffer so the content flows smoothly. Let's look at each of these tasks individually beginning with Listing 14.4.

The loop in the CGI script is an infinite loop.


Listing 14.4  Main-Loop.cgi-Main Loop Pseudocode

while(1) {
  print "Content-type: text/html\n\n",

  "<body bgcolor=ffffff>\n",
  "<title>Title of Page</title>\n",

    "<a href=\"/cgi-bin/CompleteMain.cgi?",
    "var1=$var1&var2=$var2\">",
    "<h2> Some Link Out </h2></a>\n",
    "<h2>Some banner message</h2>";

    &someFunctionThatGeneratesOutput;

    print "</body>\n",
        "                            \n" x 300,
        "-Marker-\n";
        sleep 25;
        $x++;
}

The link to the read-write transcript page should be near the top of the page, at least before the messages themselves. After the link is placed, then the script can dump the most current messages.

You've already seen the code that can do this. You reuse the same function for grabbing the transcript log file and formatting it to display to the browser (see Listing 14.5).


Listing 14.5  Cull-Transcript.cgi-Cull Transcript Log Pseudocode

sub displayTranscript {

    print "Current Transcript:<BR>\n";
    open(TRANSCRIPT, "< $LOG_FILE") || &fail("Cannot open Transcript: $!");
    print while(<TRANSCRIPT>); 
    close(TRANSCRIPT);
    
}

sub appendMessage {

    local($theUser, $theEmail, $theData) = @_;

    open(TRANSCRIPT, "< $LOG_FILE");
    @Lines = <TRANSCRIPT>;
    close(TRANSCRIPT);

    open(TRANSCRIPT, "> $LOG_FILE");
    print TRANSCRIPT "\n",
                     "On ", &today, 
                     " <A HREF=\"mailto:$theEmail\">$theUser</A>",
                     " said:<BR>\n",
                     $theData,
                     "<P>\n";
    print TRANSCRIPT @Lines;
    close(TRANSCRIPT);
}

For some operating systems, it's necessary to flush the buffer with white space. That means when a page is being pushed to the client, the script prints out data to the client. On some particular systems, this data written out can be buffered so that nothing is really sent until a specific amount of data has filled a "buffer." This amount of data necessary to fill the output buffer can vary from system to system. For your purposes, you'll assume that the buffer is about 8K, so after you write the pertinent information, you add on the end enough white space to fill the buffer and cause all the data to be sent out to the client. It isn't the most elegant solution, but on some systems it's required due to the way the system works.

Another factor is the way the CGI script is written. There are, of course, many refinements that can be made to the scripts to implement the chat applications presented. Generally, when working with buffered data, you do this when the operating system doesn't immediately send out the data to the client when we're done loading the transcript log from the file. Efficiency is the key to making the PushedChat system work. The display routines have to get the data in, format it, and dump it back out with high performance in mind. You're expecting to set a delay so the user can read all the messages. If the display routines lag behind, then the display routines dump the transcript to the browser and use up all the delay time, so by the time the user reads the first couple of messages, the whole page is reloaded. That can be really harmful to the PushedChat environment's success. If the user doesn't have a fair chance to read the messages, then it's even worse than the PlainChat environment.

There are some modifications for the PushedChat application; these are covered in the "EventChat" section at the end of the chapter. These enhancements to PushedChat involve setting up a control for the user to set a personal level of "delay" for the pushed pages so that they refresh for exactly how long the user wants. To pass this custom control you're not going to use HTML forms and hidden types, you'll pass that data within the URL of the read-only and read-write transcript pages.

It is too easy to get caught up in the little features you can add to the various applications of Web chat, so let's refocus to the standard PushedChat described in the introduction to this chapter and refresh ourselves with what kinds of problems are solved with PushedChat.

Listing 14.6 shows the program listing for the PushedChat application. This version doesn't use special modifications for graphics or filtering inappropriate content posted by users.


Listing 14.6  PushedChat.cgi-The CGI Script for the PushedChat Environment

#!/usr/local/bin/perl

@INC = ('../lib', @INC);
require 'web.pl';
%Form = &getStdin;

$Delay    = 25;

$LOG_FILE = "$ServerRoot/data/pushedchat.dat";
$Marker   = '-Marker-';
$Title    = "The PushedChat ReadOnly Transcript Page";
$Title2   = "Transcript Page for PushedChat";
$Me       = "/cgi-bin/pushedchat.cgi";
$Spacer   = "                               \n" x 200;

$theUsername = $Form{'theUsername'};
$theMessage  = &cleanMessage($Form{'theMessage'});
$theEmail    = $Form{'theEmail'};

if ($Form{'gotName'}) {
   &beginHTML;
   &buildForm('theUsername', $theUsername, 
              'theEmail',    $theEmail);
   &displayTranscript;
}
else
{
   &appendMessage($theUsername, 
                  $theEmail, 
                  $theMessage) if $theMessage;

   print "HTTP/1.0 200\n",
         "Content-type: ",
         "multipart/x-mixed-replace;",
         "boundary=$Marker\n\n",
         "$Marker\n";
   $|=1;
   $x=0;
   chop($Hostname   = 'hostname');

   $Args  = "gotName=1&";
   $Args .= "theUsername=$theUsername&";
   $Args .= "theEmail=$theEmail";

   while(1) {

     print "Content-type: text/html\n\n",
              "<body bgcolor=ffffff>\n",
           "<title>$Title</title>\n",
              "<a href=\"$Me?$Args\">",
              "<h2>Pause to add comments</h2></a>\n",
           "<hr>\n",
              "<h2>$Title</h2>";

              &displayTranscript;

        print "</body>\n",
              $Spacer,
           "$Marker\n";

     sleep $Delay;
     $x++;
    }
}

exit(0);


sub cleanMessage {

   local($theData) = $_[0];

   # any filtering, or censoring code goes here
   return $theData;
}

sub buildForm {

  local(%hiddenData) = @_;

  print "<body bgcolor=ffffff>\n", 
        "<H1>$Title2</H1>\n",
        "<FORM METHOD=\"POST\" ACTION=\"$Me\">\n",
        "Enter your comments below:<BR>\n",
        "<TEXTAREA ROWS=5 COLS=60 NAME=\"theMessage\">\n",
        "</TEXTAREA>\n",
        "<P>\n",
        "<INPUT TYPE=\"SUBMIT\" VALUE=\"Transmit\">\n",
        "<INPUT TYPE=\"SUBMIT\" VALUE=\"Refresh\"><BR>\n",
        "<p>\n";

  foreach $dataItem (keys %hiddenData) {
     print "<INPUT TYPE=\"HIDDEN\" NAME=\"$dataItem\" ",
           "VALUE=\"$hiddenData{$dataItem}\">\n";
  }
  print "<INPUT NAME=\"inChat\" TYPE=\"HIDDEN\">\n",
        "</FORM>\n",
        "<P>\n",
        "<A HREF=\"/index.html\">Back Home</A><P>\n";
}
   


sub displayTranscript {

    print "Current Transcript:<BR>\n";
    open(TRANSCRIPT, "< $LOG_FILE") || 
         &fail("Cannot open Transcript: $!");
    print while(<TRANSCRIPT>); 
    close(TRANSCRIPT);
    
}

sub appendMessage {

    local($theUser, $theEmail, $theData) = @_;

    open(TRANSCRIPT, "< $LOG_FILE");
    @Lines = <TRANSCRIPT>;
    close(TRANSCRIPT);

    open(TRANSCRIPT, "> $LOG_FILE");
    print TRANSCRIPT 
         "\n",
         "On ", &today, 
         " <A HREF=\"mailto:$theEmail\">$theUser</A>",
         " said:<BR>\n",
         $theData,
         "<P>\n";
    print TRANSCRIPT @Lines;
    close(TRANSCRIPT);
}


sub today {

  local(@tD) = localtime(time);

  return sprintf("%d/%d/%d, %02d:%02d:%02d %s",
                 $tD[4], $tD[3], $tD[5],
                 $tD[2]>12?$tD[2]-12:$tD[2]==0?12:$tD[2],
                 $tD[1], $tD[0], 
                 $tD[2]>12?"pm":"am");
}

Problems Solved with PushedChat

The main problem you saw with PlainChat and BusyChat was the user interface. The user interface of the PlainChat-type environments was set up so that on every page, the users had the opportunity to add a comment to the discussion. One limitation was that after a new message was posted, they had to manually reload the page to see if anything new had been posted. If the user clicked the Reload button built into the browser, the situation was worse because normally the browser will ask if you want to "repost form data." The answer every time should be "no" because "yes" would mean reposting the identical message again! The PlainChat application included a special submit button in the form on the page so that when clicked, it would perform the "no-operation": reload the page without asking any questions. Still, this seems tedious and a Web chat environment should be much more realistic and easier to use than that.

The problems of PlainChat and Web chats like it are partially solved by PushedChat. The advantage of PushedChat is that the user doesn't need to keep her finger on the mouse button to interact. The main feature of PushedChat is that dialog is refreshed for the user automatically. As new posts are made, the user sees them. Only when the user is interested in making her own comments does she need to reach and click.

The Web is a medium where clicking and navigating are necessary to find useful information, but the task of communication through the Web interface should not be hindered by the necessity of clicking things. PushedChat was presented as a solution for communication in the Web where the central theme was making the Web chat easier to use and more realistic.

The realism of PushedChat can be described best by using examples of real-life events and applying the application to enhance the event within the Web environment. For instance, any type of event where information is constantly changing-sports scores, news bulletins, or even diagnostics about the Web server-can be implemented using core elements of the PushedChat application.

PushedChat has the advantage of being more realistic and real-time because of Server Push. Without Server Push, PushedChat wouldn't work at all. But since you have the luxury of pushing pages automatically onto the browser, you can take a look at some of the examples up close and see exactly how they can be applied to PushedChat.

The Web owes a lot to the sports world. There are so many events and competitions now that it almost seems crazy to think that more sports-related Web sites are not competing for content. Imagine a sports tournament. A Web company doing a good job of posting current stats and standings of teams as they made their way through the tournament would surely get a mention in Wired magazine for covering the event "on the Web." As a user on the Web, you almost expect these sites to exist. On the tournament Web site, users could get detailed information without traveling thousands of terrestrial miles from their home country. On the Web, users could follow their team and learn about the nation represented by the team and the myriad links from there.

In addition to the complex systems in place for keeping stats current, a side line area for users for commenting in real-time about the event is a sure attraction. A special "host" monitoring the event would electronically grant access to a "studio audience" (by allowing them the URL to see the event on the Web). Once comfortable in their virtual studio, the host announces the special guest or panel to take questions from the audience. The host would have control over all the questions channeled to the panel or special guest. Plus, the replies and comments made throughout the event would be filtered by the host. Of course, any Web event like this would require days of preparation to get all the high profile parties on track. In addition, software would be necessary to help the host monitor the event.

The PushedChat application only partially completes this idea. On top of the chat environment there would need to be other dynamic pages and systems to monitor and queue up questions. We'll be sure to cover those higher level modules in the "EventChat" section of this chapter for those eager to create their own custom EventChat environment.

Types of PushedChat Environments

Among all the types of Web chat environments, the PushedChat is the best one so far to be equipped with cool enhancements. You learned in the last chapter the topic of graphics associating a user with her messages in the transcript log page. In this section, you learn how to implement graphical icons to appear next to each message of a PushedChat session. Also, you see how to add a simple censor filter to do a quick check on words you might not want to appear in your transcript log. Finally, you learn about techniques on adding a "chat-cam" function to the PushedChat environment so that you can keep a snapshot of the messages as they appear in the transcript log.

Web chat environments are more interesting if you can add more to them than the ability to type text and see it in real-time. Graphics can play a significant role in the popularity of a Web chat environment. These are the types of graphics that are small, thumbnail icons showing either a user's face, some cartoon character, or miscellaneous icon. It is really up to the interface designer (your graphics and development people) to decide what motif you want to give the chat environment. Let's start with generic icons pre-made by your team for the Web chat.

To select the types of icons, let's set the stage for the Web chat. Your Web chat environment will be about rock climbing. You're going to have a host for the chat who will just be participating to fuel discussion and answer some general questions. This isn't a celebrity chat so you're not expecting a rush of users swarming to the site driving the load (and noise) level up. The host plans to start the discussion about a recent climb to Mount Rainier. The host is the president of a local climbing club in the Pacific Northwest. For icons, you're going to choose different types of equipment a climber might use-a wool hat, a compass, a pair of boots, a bundle of rope, a first-aid kit, a map, a water bottle, and more. Pick about a dozen different icons to start with (see Fig. 14.3).

Figure 14.3: A few icons to help the users pick a specific personality trait to associate with their "identity" in the Web chat environment.

The login page for the Web chat environment is the first place to introduce the user to the icons. By the place where they enter their name, they can select the icon of their choice by clicking it directly. If you don't expect your users to be using a browser capable of "image" submit buttons, you can use radio-type buttons by each icon. For the first example, you'll set up the page so that clicking the icon will be the same as "submitting" the data and take them to the main read-only page of the PushedChat environment (see Listing 14.8).


Listing 14.8  Icon-Login.html-Login Page with Graphical Icons for the User to Identify With

<HTML>
<TITLE>Login Page for PushedChat with Icons</TITLE>
<BODY BGCOLOR=FFFFFF>
<H1>Login Page for PushedChat with Icons</H1>
<P>
Please enter your name below:<BR>
(Example: Pat Smith)<BR>
<FORM METHOD=POST ACTION="/cgi-bin/pushedchat.cgi">

<INPUT NAME="theUsername"><BR>

Please enter your E-mail address below:<BR>
(Example: pat@some.place.com)<BR>
<INPUT NAME="theEmail">
<P>

Pick a Icon for yourself:<br>

<table>
<tr>
<td width=90><img src="/icons/afraid.gif"></td>
<td width=90><img src="/icons/bert.gif"></td>
<td width=90><img src="/icons/devil.gif"></td>
<td width=90><img src="/icons/heartsm.gif"></td>
<td width=90><img src="/icons/ren.gif"></td>
<td width=90><img src="/icons/smiley.gif"></td>
<td width=90><img src="/icons/stimpy.gif"></td>
<td width=90><img src="/icons/tigger.gif"></td>
</tr>
<tr>
<td width=90>afraid</td>
<td width=90>bert</td>
<td width=90>devil</td>
<td width=90>heartsm</td>
<td width=90>ren</td>
<td width=90>smiley</td>
<td width=90>stimpy</td>
<td width=90>tigger</td>
</tr>
<tr>
<td width=90><input type="radio" name="icon" value="afraid"  checked></td>
<td width=90><input type="radio" name="icon" value="bert" ></td>
<td width=90><input type="radio" name="icon" value="devil" ></td>
<td width=90><input type="radio" name="icon" value="heartsm" ></td>
<td width=90><input type="radio" name="icon" value="ren" ></td>
<td width=90><input type="radio" name="icon" value="smiley" ></td>
<td width=90><input type="radio" name="icon" value="stimpy" ></td>
<td width=90><input type="radio" name="icon" value="tigger" ></td>
</tr>
</table>


<INPUT TYPE=SUBMIT VALUE="Enter PushedChat">
</FORM>

</BODY>
</HTML>

The real login page for PushedChat with icons uses server-side includes (SSI) to generate the list of icons and names (see Listing 14.9).


Listing 14.9  ssi-icon-pushed-login.html-Login Page for PushedChat with Icons

<HTML>
<TITLE>Login Page for PushedChat with Icons</TITLE>
<BODY BGCOLOR=FFFFFF>
<H1>Login Page for PushedChat with Icons</H1>
<P>
Please enter your name below:<BR>
(Example: Pat Smith)<BR>
<FORM METHOD=POST ACTION="/cgi-bin/pushedchat.cgi">

<INPUT NAME="theUsername"><BR>

Please enter your E-mail address below:<BR>
(Example: pat@some.place.com)<BR>
<INPUT NAME="theEmail">
<P>

Pick a Icon for yourself:<br>

<!--#exec cmd="/t2/home/jdw/bookweb/cgi-bin/listIcons.pl" -->

<INPUT TYPE=SUBMIT VALUE="Enter PushedChat">
</FORM>

</BODY>
</HTML>

The SSI script listIcons.pl reads a directory full of icons and generates the HTML table with each icon listed and the name of the icon below. A mutally exclusive radio button is preset on the first one, but the users can pick any one they like.

Our goal for the login page is to get the user's name and which icon she wants to use. Once she selects an icon, the data is passed to the CGI script to begin the Web chat environment.

Pointers to Modifying the Application

Again, refreshing ourselves of the basis of PushedChat, the new technology for this application is the ability for a server to push pages automatically to the browser. Another example of how this application fits into real-world situations, consider the Web server itself. It's a group of programs and systems that is running on a machine connected to the Internet. The Webmaster is concerned greatly about the "uptime" of the server, how many "hits" the server gets, and a few dozen other issues as well.

If you start with three attributes of a Web server, let's illustrate a situation where Server Push can be used. Consider a Perl script written to take "the pulse and temperature" of a Web server running on a UNIX machine (see Listing 14.10).


Listing 14.10  WebStats.cgi-Using Server Push to Display Server Statistics

#!/usr/local/bin/perl

@INC = ('.', @INC);
require 'web.pl';
require 'timelocal.pl';

%Form = &getStdin;
%Months = ('Jan', 0, 'Feb', 1, 'Mar', 2, 'Apr', 3, 'May', 4, 'Jun', 5, 
           'Jul', 6, 'Aug', 7, 'Sep', 8, 'Oct', 9, 'Nov', 10, 'Dec', 11);


$LOG_FILE = "$ServerRoot/logs/httpd.pid";
$ACCESS_FILE = "$ServerRoot/logs/access_log";

print "HTTP/1.0 200\n",
      "Content-type:",
      " multipart/x-mixed-replace;",
      "boundary=$Marker\n\n",
      "$Marker\n";

while(1) {
   @fpid_stats = stat($LOG_FILE);
   @facc_stats = stat($ACCESS_FILE);
   open(PID, "< $ServerRoot/logs/httpd.pid");
   $pid = <PID>;
   close PID;
   chop(@ps = '/usr/bin/ps -ef');
   @running = grep(/\w+\s+\d+\s+(\d+)/ && $1 == $pid, @ps);
   $runOk = $#running+1;;
   $now = time;
        print "Content-type: text/html\n\n",
        "<body bgcolor=ffffff>\n";
   print "<OL>\n",
         "  <LI><strong>Server Status</strong><BR>\n";
   print "The web ",
         $runOk?"is running with $runOk spawned servers.":"is not running.",
"\n";
   print "  </LI>\n",
         "  <LI><strong>Up Time</strong><BR>\n";

   if ($runOk) {
       $upTime = $now - $fpid_stats[9];
   }
   else
   {
       $upTime = $now - $facc_stats[9];
   }
   
   print "$upTime seconds elapsed since ",
         $runOk?"the web server was started.":"the last page was accessed",
         "  </LI>\n",
         "  <LI><strong>Hits in the last 24 hours</strong><BR>\n";

   ($sec, 
    $min, 
    $hour, 
    $mday, 
    $mon, 
    $year, 
    $wday, 
    $yday, 
    $isdst)=localtime($now);

    open(AF, "< $ACCESS_FILE");
    while(<AF>) {
       next unless &within24hrs($_);
       $x++;
       last;
    }
    while(<AF>) {
       $x++;
    }

    print "$x hits within the last 24 hours.\n",
          " </LI>\n",
          " <LI><strong>Size of Access Log files:</strong><BR>\n";

   ZZprint "  $ACCESS_FILE : ", -s $ACCESS_FILE, "<BR>\n",
      " </LI>\n",
      "</OL>\n",
     
        "                                                          \n" x 200,
        "--ThisRandomString--\n";
        sleep 25;
        $x++;
    }



#####


sub within24hrs {

 local($line) = $_[0];

 $line =~ /\[(\d+)\/(\w+)\/(\d+)\:(\d+)\:(\d+)\:(\d+)/;

    
 $year = $3 - 1900;
 $month = $Months{$2};
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)=localtime($now);
 $tt = &timelocal($6, $5, $4, $1, $month, $year, 0, 0, 0);
 $tt = $now - $tt;
 return $tt<=86400?$tt:0;
}

If a module of code like this was inserted into the PushedChat framework, you have a system of getting up-to-the minute statistics on the Web's condition. This isn't necessarily the best approach to watching the Web server since the "visual real-estate" taken up by a Web client on your screen would hide your other windows. But the technology of Server Push can be applied to several types of Web chat environments, even when there are not actual people "talking." A system can be constructed to handle instructions (the messages) and a status report can be generated on a regular basis (the transcript page).

EventChat

The EventChat metaphor describes the function of a Server Push environment where the content is based on a one-time occurrence. EventChat is a label for an application that includes the live event with the Web site. Sporting events and celebrity Q&A sessions are popular reasons for building EventChat environments. This section covers three enhancements made to PushedChat that work well within the EventChat metaphor.

User Control of Refresh Delay

It is better to allow the user some control for how much time passes before the transcript page is refreshed. You can place a control on the login page and transcript pages to let the user change the operational characteristics of the chat-reloading time interval.

Chat Monitor

In higher volume chat environments, it becomes necessary to check the conduct of the participants of the chat environment. In a live-event siuation, it is a politically sensitive matter to control the content of the chat environment.

Question Queue

Likewise, in high-volume chat environments there might be an overload of interest in the guest of the Web chat event. All of these chat environments need to employ a method for queueing messages in order. The list of messages can be handled in order, each message getting a review by the moderator/monitor, finally appearing on the window for the guest to answer if approved.