Count with CGI/HTTP

A CGI program can be any executable. In this particular implementation, we use Java. In our case, the CGI server must be called through a batch file. We do not use forms, so the client code has to create and send a POST request to the Web server. It can be done, because applets are allowed to connect to the servers from which they have beed loaded.

In this implementation, we will not use any database. Code to handle a databse would clutter the example, which is made to be easy to follow. The consequence of this is that the value of count is stored inside the client, because HTTP is stateless. The value is sent to the server for processing, and then the increased value is returned. This design allows for measuring the delay involved in using the CGI/HTTP technique for invoking remote operations.

HTML File for the Applet

<h1>Count CGI Client Applet</h1>
<hr>
<center>
  <applet
    code=CountCGIClientApplet.class codebase=classes width=300 height=60>
  </applet>
</center>
<hr>

The Client Applet

This code implements the event model of JDK 1.0.2.

The client ignores all but the last line of the message returned from the server. This is because the server does not know whether it is talking to a browser or another application. In our case, we do not need the HTTP header information (something that a browser would need).

// CountCGIClientApplet.java, Java CGI Applet

import java.awt.*;
import java.io.*;
import java.net.*;

public class CountCGIClientApplet extends java.applet.Applet
{
  private TextField countField, pingTimeField;
  private Button runCount;
  private Counter.Count counter;

  public void init()
  {
    // Create a 2 by 2 grid of widgets.
    setLayout(new GridLayout(2, 2, 10, 10));

    // Add the four widgets, initialize where necessary
    add(new Label("Count"));
    add(countField = new TextField());
    countField.setText("1000");
    add(runCount = new Button("Run"));
    add(pingTimeField = new TextField());
    pingTimeField.setEditable(false);
  }

  public boolean action(Event ev, Object arg)
  {
    if(ev.target == runCount)
    { try
      { String sum = "0";

        // get count, initialize start time
        showStatus("Incrementing.");
        int count = new Integer(countField.getText()).intValue();
        long startTime = System.currentTimeMillis();

        // Increment count times
        for (int i = 0 ; i < count ; i++ )
        { sum = increment(sum);
        }

        // Calculate stop time; show statistics
        long stopTime = System.currentTimeMillis();
        pingTimeField.setText("Avg Ping = "
          +  ((stopTime - startTime) / (float)count) + " msecs");
        showStatus("Sum = " + sum);
      } catch(Exception e)
      { showStatus("System Exception" + e);
      }
      return true;
    }
    return false;
  }
 

  public String increment(String currentSum)
  { String script = "/cgi-bin/Count.bat";
    Socket socket = null;
    String rdata = "";
    String line = "";
    String lastLine = "";

    try
    {
       socket = new Socket("www.somewhere.net", 80);
       DataOutputStream ostream
          = new DataOutputStream(socket.getOutputStream());
       DataInputStream istream
          = new DataInputStream(socket.getInputStream());

       ostream.writeBytes("POST " + script
          + " HTTP/1.0\r\n"
          + "Content-type: application/octet-stream\r\n"
          + "Content-length: "
          + currentSum.length() + "\r\n\r\n");
       ostream.writeBytes("Increment " + currentSum);

       while ((line = istream.readLine()) != null)
       { lastLine = line;
         rdata += line + "\n";
       }

       istream.close();
       ostream.close();
      }
      catch (Exception e)
      {  showStatus("Error " + e);
         if (socket != null)
            try
            { socket.close();
            }
            catch (IOException ex) {}
      }
      return lastLine;
   }
}
 

CGI Batch file

The sole line in the c:\cgi-bin\Count.bat file starts a JVM with the CountCGIServer:

c:\java\bin\java CountCGIServer

The server

// CountCGIServer.java, Java CGI Server Program

import java.io.*;
import java.util.*;

class CountCGIServer
{ public static void main(String[] args)
  { int count;
    String line;

    try
    { // create streams
      DataInputStream istream = new DataInputStream(System.in);
      DataOutputStream ostream = new DataOutputStream(System.out);

      // execute client requests
      line = istream.readLine();
      StringTokenizer tokens = new StringTokenizer(line);
      String myOperation = tokens.nextToken();

      // perform increment operation
      if(myOperation.equals("increment"))
        { String countString = tokens.nextToken();
          count = Integer.parseInt(countString);
          count++;
          ostream.writeBytes("" + count);
        }

      // close streams
      istream.close();
      ostream.close();
   }
   catch (Exception e)
   {  System.out.println("Error " + e);
   }
 }
}
 

Running the Application

The following several steps are involved in running the CGI/HTTP version of Count: