Home : Course Map : Chapter 15 :
Client for the Experiment Simulation
JavaTech
Course Map
Chapter 15

Client/ServerDesign
Processing Steps
Data Server
Run Data Server
    Demo 1
Data Client
DataClient Applet
    Demo 2
Client/Server Sim
SimServer
    Demo 3
SimClient
Run SimClient
    Demo 4
Exercises

     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

The applet SimClient shown below connects to the SimServer program via a socket connection. The user enters the number of drops to make and the sigma (standard deviation) on the smearing of the position measurements of the mass as it drops.

Four buttons control the program. "Connect/Disconnect" makes or breaks the connection to the server. "Exit" ends the program when it runs in application mode. "Run Sim" tells the server to start the simulation, and "Clear" will clear the data plots.

The host field at the top provides the address for the server. (It defaults to 127.0.0.1 for the local machine.) The user name is used in the login with the server.

The top plot shows the position versus time of each drop as the data arrives. The bottom plot fits a quadratic polynomial to the average position vs. time of all the drops. This fit produces the value of the gravitational acceleration constant. (See Chapter 9: Physics for more about this simulation.)


SimClient Application/Applet

SimClient.java - derived from the demonstration program Ch.9: Physics: DropTestAnalysisApplet. The mass drop classes became part of the server simulation. The fields at the top allow the user to enter the number of drops the simulator should execute and what smearing (std. dev.) should be made on the data points. When a connection is made to the sever, a SimClientWorker object is created to take care of all communications with the server.

The Drop Event plot shows data from each drop while the bottom plot fits a line through the average Y vs. time data. This fit provides the gravitational constant value shown at the bottom.

SimClientWorker.java - tends the socket connection to the server. Sends and obtains setup parameters, obtains the data from the simulator, and tells the SimClient when the run is finished.

NetStreamMethods.java - convenient utility class with methods for reading and writing over the socket streams. (Code on SimServer page.)

SimUtil.java - another convenience class that holds some constants used in the communications protocols. (Code on SimServer page.)

+ Previous classes:
Ch. 9: Physics: DropAnalyzer.java

Ch. 8: Physics:
Fit.java, FitPoly.java, DrawPoly.java
Ch. 6: Tech: DrawPanel.java, DrawPoints.java, DrawFunction.java
Ch. 6: Tech: PlotPanel.java, PlotFormat.java

package SimClientServer;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.net.*;


/**
  *
  *  A Client for a Prototype Remote Simulation System
  *
  *  SimClient controls a mass drop simulation run by SimServer. SimClient
  *  contacts the server and the server assigns a simulator to the client. The
  *  client in turn assigns a SimClientWorker to deal with the exchange of
  *  messages to set up the simulation and to get the data from the simulation.
  *
  *  SimClient runs both as a standalone app or in a browser web page.
  *
  *  The User Interface displays several items of interest:
  *
  *   - The host IP and username are displayed in TextFields and can be altered.
  *   - Disconnect/Connect button can interrupt and restart the connection.
  *   - Run Sim button tells the server to run the sim and begin sending the data
  *   - Text fields allow user to set the number of drops and the sigma error on
  *     the simulated drop measurements.
  *   - A label displays the status of the connection
  *   - A TextArea displays status messages for the client/server exchange
  *   - One histogram displays individual drop data.
  *   - The second histogram displays the average Y vs time and a fit to the
  *     curve. The parameters of the fitted curve provide the "g" value
  *     displayed in a TextField at the bottom.
  *
  *  The thread class SimClientWorker is used to send  requests for data
  *  and to read the data.
  *
 **/
public class SimClient extends JApplet
             implements ActionListener
{
  // GUI setup

  // Use a DrawPanel to draw the data for each event
  DrawPanel fDrawDataPanel;
  DrawPoints fDrawPoints;
  double [][] fDataPointsArray;

  // The DropAnalyzer will have its own panel and histogram.
  DropAnalyzer fDropAnalyzer;

  // UI components
  JLabel     fStatusLabel  ;
  JTextField fHostField    ;
  JTextField fUserNameField;
  JTextField fNumDropsField;
  JTextField fSigmaField   ;
  JTextArea  fMessageArea  ;

  // Flag for whether the applet is in a browser
  // or running via the main () below.
  boolean fInBrowser = true;

  //Buttons
  JButton fStartButton;
  JButton fClearButton;
  JButton fExitButton;
  JButton fRunSimButton;

  // Networking setup

  // Properties needed for the connection setup
  Socket  fServer;;
  SimClientWorker fSimClientWorker;
  Thread fSimClientThread;

  int fDataServerPort = 2222; // use 2222 as default
  String fClientPort;
  String fHost     = "127.0.0.1";
  String fUserName = "Smith";

  // Data setup
  // Amount of data in each set read from the server
  int fMaxDataMeasurements = 40;
  int fNumDrops  = 10;
  double fSigmaY = 1.0; // Smearing std.dev. for y positions
  double fTFrame = 0.020; // in secs

  // Dimensions for the drop area.
  double fYBallStart = 200.0; // cm
  double fYBallEnd   =   0.0; // cm

  // Range of the drop time.
  double fTStart = 0.00; // sec
  double fTEnd   = 0.75; // sec

  boolean fConnected = false; // flag for connection status
  String fMsgLine    = "";    // String displayed in status TextField
  String fDataLine   = "";    // String displayed in data TextArea

  int fTimeUpdate = 500; // read data every 500 msecs

  // Arrays to hold setup parametes for the simulation.
  int    [] fISetup;
  double [] fDSetup;

  /** Create a User Interface with a textarea with scroll bars
    * and a Go button to initiate processing and a Clear button
    * to clear the textarea.
   **/
  public void init () {

    // Creat a DrawPoints instance and a DrawPanel panel
    // to display data points.
      fDrawPoints = new DrawPoints ();
      fDrawPoints.setSymbolType (DrawPoints.RECT);

      DrawFunction [] draw_functions = new DrawFunction[1];
      draw_functions[0] = fDrawPoints;
      fDataPointsArray = new double[4][];

      // Initially the points arrays are all null;
      fDrawPoints.setParameters (null, fDataPointsArray);

      fDrawDataPanel = new DrawPanel (fYBallEnd, fYBallStart,
                                    fTStart, fTEnd, draw_functions);

      fDrawDataPanel.setTitle ("Drop Event Data");

      // Create the analyzer.
      fDropAnalyzer = new DropAnalyzer (fYBallEnd, fYBallStart,
                                      fTStart, fTEnd);

      // Initialize the setup arrays. They are passed to the
      // server to set up the simulation.
      fISetup = new int[2];
      fISetup[0] = fNumDrops;
      fISetup[1] = fMaxDataMeasurements;

      fDSetup = new double[2];
      fDSetup[0] = fSigmaY;
      fDSetup[1] = fTFrame;

      // Get the DrawPanel from the analyzer
      JPanel drop_analyzer_panel = fDropAnalyzer.getPanel ();

      // Add the two data panels
      JPanel data_panels = new JPanel (new GridLayout (2,1));
      data_panels.add (fDrawDataPanel);
      data_panels.add (drop_analyzer_panel);


    // Control fields

      // First provide the inputs field for the host IP
      // and for the user name.
      fHostField = new JTextField (fHost,16);
      JLabel host_label = new JLabel ("Host: ");
      host_label.setHorizontalAlignment (SwingConstants.RIGHT);
      fUserNameField    = new JTextField (fUserName,16);
      JLabel name_label = new JLabel ("User Name: ");
      name_label.setHorizontalAlignment (SwingConstants.RIGHT);

      // Top line of controls = host and name inputs
      JPanel ctrls_panel1 = new JPanel ();
      ctrls_panel1.add (host_label);
      ctrls_panel1.add (fHostField);
      ctrls_panel1.add (name_label);
      ctrls_panel1.add (fUserNameField);

      // Next line holds the buttons, and the data
      // channel number to monitor.
      fStartButton = new JButton ("Connect");
      fStartButton.addActionListener (this);
      fClearButton = new JButton ("Clear");
      fClearButton.addActionListener (this);
      fExitButton = new JButton ("Exit");
      if ( fInBrowser)
          fExitButton.setEnabled (false);
      else
          fExitButton.addActionListener (this);
      fRunSimButton = new JButton ("Run Sim");
      fRunSimButton.setEnabled (false);
      fRunSimButton.addActionListener (this);

      JPanel buttons_panel = new JPanel (new GridLayout (2,2));
      buttons_panel.add (fStartButton);
      buttons_panel.add (fClearButton);
      buttons_panel.add (fExitButton);
      buttons_panel.add (fRunSimButton);

      JLabel num_drops_label = new JLabel ("Num Drops");
      num_drops_label.setHorizontalAlignment (SwingConstants.CENTER);
      fNumDropsField = new JTextField (Integer.toString (fNumDrops),5);

      JLabel sigma_label = new JLabel ("Sigma");
      sigma_label.setHorizontalAlignment (SwingConstants.CENTER);
      fSigmaField = new JTextField (Double.toString (fSigmaY),5);

      JPanel inputs_panel = new JPanel (new GridLayout (2,2));
      inputs_panel.add (fSigmaField);
      inputs_panel.add (sigma_label);
      inputs_panel.add (num_drops_label);
      inputs_panel.add (fSigmaField);

      fStatusLabel = new JLabel ("DisfConnected");
      fStatusLabel.setForeground (Color.RED);
      fStatusLabel.setHorizontalAlignment (SwingConstants.CENTER);

      // Now pack the components of the second ctrls
      // line of components
      JPanel ctrls_panel2 = new JPanel ();
      ctrls_panel2.add (buttons_panel);
      ctrls_panel2.add (inputs_panel);
      ctrls_panel2.add (fStatusLabel);

      // Put the 2 lines of controls into a sub-panel
      JPanel ctrls_panel12 = new JPanel ();
      ctrls_panel12.add (ctrls_panel1);
      ctrls_panel12.add (ctrls_panel2);

      fMessageArea = new JTextArea ();
      fMessageArea.setEditable (false);
      // Add to a scroll pane so that a long list of
      // computations can be seen.
      JScrollPane area_scroll_pane = new JScrollPane (fMessageArea);

    // Use a GridBagLayout to apportion space for the
    // controls, text area and histograms.
    JPanel mainPanel = new JPanel (new GridBagLayout ());

    GridBagConstraints c = new GridBagConstraints ();
    c.fill = GridBagConstraints.BOTH;

    // Put ctrls at top
    c.gridx = 0;
    c.gridy = 0;
    c. weightx = 1.0;
    c. weighty = 0.05;
    mainPanel.add (ctrls_panel12,c);

    // Put text area below the controls
    c.gridx = 0;
    c.gridy = 1;
    c. weightx = 1.0;
    c. weighty = 0.25;
    mainPanel.add (area_scroll_pane, c);

    // Put histograms in rest of the vertical space
    c.gridx = 0;
    c.gridy = 2;
    c. weightx = 1.0;
    c. weighty = 0.70;
    c.insets = new Insets (2,2,10,2);
    mainPanel.add (data_panels, c);

    // Add text area with scrolling to the contentPane.
    add (mainPanel);

  } // init

  /** Respond to the buttons. **/
  public void actionPerformed (ActionEvent e)  {
    Object source = e.getSource ();
    if (source == fStartButton) {
        if ( fStartButton.getText ().equals ("Connect"))
            start ();
        else
            stop ();
    }
    else if (source == fRunSimButton) {
        initExpt ();
        fSimClientWorker.startRun (fISetup,fDSetup);
        fRunSimButton.setEnabled (false);
        fStartButton.setEnabled (false);
    }
    else if (source == fClearButton) {
        // Clear the data points display
        fDataPointsArray[0] = null;
        fDrawPoints.setParameters (null, fDataPointsArray);

        // Reset the analysis display.
        fDropAnalyzer.reset ();
        repaint ();
    }
    else if (source == fExitButton  && !fInBrowser){// Exit button
        fSimClientWorker.finish ();
        System.exit (0);
    }
  } // actionPerformed

  /**
    * Make the connection to the server. Set up the DataReader
    * and begin recording the data from the server.
   **/
  public void start () {
    // End the current connection if already fConnected.
    if  ( fConnected) stop ();

    // Now try to connect to the DataServer
    try {
      if (!connect ()) {

        println ("* NOT CONNECTED *");
        fStatusLabel.setText ("DisfConnected");
        fStatusLabel.setForeground (Color.RED);
      }
    }
    catch  (IOException e){
      println ("* NOT CONNECTED *");
      fStatusLabel.setText ("DisfConnected");
      fStatusLabel.setForeground (Color.RED);
    }
  } // start

  /**
    *  Connect to the server via a socket. Throws IOException
    *  if socket connection fails.
   **/
  boolean connect () throws IOException {

    // Get the current values of the host IP address and
    // and the username. These can't change after the connection
    // is made;
    fHost = fHostField.getText ();
    fUserName = fUserNameField.getText ();

    println ("Attempting to connect to server ...");

    try {
       // Connect to the DataHost using the host IP address
       // and the port at the server location
       fServer = new Socket (fHost, fDataServerPort);
    }
    catch (SecurityException se){
       println ("Security Exception:\n"+se);
       return false;
    }

    println ("Server fConnected - create worker");

    // Create the worker to tend to this server
    fSimClientWorker = new SimClientWorker (this, fServer, fUserName);
    fSimClientThread = new Thread (fSimClientWorker);
    fSimClientThread.start ();

    return true;
  } // connect

  /**  Get ready for the running of the simulation. **/
  void initExpt () {
    // Clear the data points display
    fDataPointsArray[0] = null;
    fDrawPoints.setParameters (null, fDataPointsArray);

    // Get the current values of the host IP address and
    // and the username
    fHost = fHostField.getText ();
    fUserName = fUserNameField.getText ();
    try {
       fNumDrops = Integer.parseInt (fNumDropsField.getText ());
       fSigmaY   = Double.parseDouble (fSigmaField.getText ());
    }
    catch (NumberFormatException ex) {
      println ("Bad field value");
      return;
    }

    // Tell the analyzer how many drops will be made and how many
    // measurements per drop.
    fDropAnalyzer.initRun (fNumDrops, fMaxDataMeasurements);

    // Reset the analyzer.
    fDropAnalyzer.reset ();

    // Put the new parameter values in the setup arrays
    // for passing to the simulation.
    fISetup[0] = fNumDrops;
    fDSetup[0] = fSigmaY;

  } // initExpt

  /**
    * Can change the scaling on the analsys chart to reflect
    * changes in the experiment setup.
   **/
  public void setExptParameters (double [] params) {

    fYBallEnd   = params[0];
    fYBallStart = params[1];
    fTStart     = params[2];
    fTEnd       = params[3];

    fDropAnalyzer.setScaleLimits (fYBallEnd, fYBallStart,
                                fTStart, fTEnd);
    fDrawDataPanel.setScaleLimits (fYBallEnd, fYBallStart,
                                 fTStart, fTEnd);

  } //setExptParameters

  /** Stop the worker thread. **/
  public void stop () {
    // Disconnect and kill the fSimClientWorker thread
    println ("Stop worker");
    fSimClientWorker.finish ();
    setDisconnected ();
  } // stop

  /**
    * When connection made by the SimClientWorker, it calls back
    * to this method to let the parent know that.
   **/
  void setConnected () {

    // Can't change the host or username while the connection
    // is active
    fHostField.setEnabled (false);
    fUserNameField.setEnabled (false);

    // Set connect flag and set buttons button text
    fConnected = true;
    fStartButton.setText ("Disconnect");
    fRunSimButton.setEnabled (true);

    // Indicate fConnected status on the user interface
    fStatusLabel.setText ("Connected");
    fStatusLabel.setForeground (Color.BLUE);
  } // setConnected

  /**
    * When connection stopped, reset the user interface.
    * The SimClientWorker object calls this method in the parent
    * when the connection to the server is broken.
   **/
  void setDisconnected () {

    // Switch the buttons for restart
    fStartButton.setText ("Connect");
    fStartButton.setEnabled (true);
    fRunSimButton.setEnabled (false);
    fStatusLabel.setText ("Disconnected");
    fStatusLabel.setForeground (Color.RED);
  } // setDisfConnected

  /**
    *  The SimClientWorker passes the data array from the server here.
    *  Display the data set by packing a histogram.
    *
    *  Also, plot the distribution of one of the channels of the data.
    *  The channel number is given in the text field.
   **/
   void setData (double [][] data) {

      // First display the set of data. The setParameters () method
      // in DrawPoints need a 2-d array argument. Here
      // the top 2 arrays will be null since there are no errors
      // on the horizontal and vertical coords.
      fDataPointsArray[0] = data[0]; // time array
      fDataPointsArray[1] = data[1]; // position measurements

      // Display the position values in each
      fDrawPoints.setParameters (null, fDataPointsArray);
      fDrawDataPanel.repaint ();

      // Analyze data for each drop
      fDropAnalyzer.analyzeDrop (data[0], data[1], data[0].length);

   } // setData

  /** Run has finished. **/
  void runDone () {

    // Analyze the data collected from the set of drops.
    fDropAnalyzer.analyzeRun ();

    // Reset user interface
    fRunSimButton.setEnabled (true);
    fStartButton.setEnabled (true);
    repaint ();
  } // runDone


  /**
    * Convenience method for sending messages to the
    *  text area.
   **/
  public void println (String str) {
     fMessageArea.append (str +"\n");
     repaint ();
  }

  /** Run the program as an application. **/
  public static void main (String[] args) {
    //
    int frame_width=500;
    int frame_height=650;

    // Create standalone version
    SimClient applet = new SimClient ();
    applet.fInBrowser = false;
    applet.init ();

    // Following anonymous class used to close window & exit program
    JFrame f = new JFrame ("Simulation Clent");
    f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

    // Add applet to the frame
    f.getContentPane ().add ( applet);
    f.setSize (new Dimension (frame_width,frame_height));
    f.setVisible (true);
  }  // main

}  // class SimClient
package SimClientServer;

// Begun from StartJApplet11

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

/**
  * SimClient creates this Runnable class to tend to the connection
  * to the experiment simulation server. It first sets up the streams via the
  * socket to the server and then does a login procedure.
  *
  * The SimClient presents the GUI to the user and holds the DropAnalysis
  * instance to examine the data from the simulation at the server. The instance
  * of SimClientWorker takes care of the communications with the server.
  *
  * After obtaining from the servers the parameters of the simulation, this
  * object sends the run setup info  (e.g. number of drops events to execute)
  * and then waits for the SimClient to invoke start the run.
**/
public class SimClientWorker extends NetStreamMethods
                             implements Runnable
{
  // Reference to the parent program that opens this worker.
  SimClient fClient;

  // Networking
  Socket fServer;
  String fUserName;

  // Miscellaneous array buffers and utility variables
  int [] fISetup;
  double [] fDSetup;
  double [][] fData = new double [2][];

  int fServerCmd = 0;
  boolean fKeepRunning = true;

  /**
    *  Receive the DataClient to provide with the data
    *  from the server.
   **/
  public SimClientWorker (SimClient c, Socket server, String userName) {
    fClient = c;
    fServer = server;
    fUserName = userName;
  } // ctor

  /**
    * Remain in a loop to monitor the I/O from the server.
    * Display the data.
   **/
  public void run () {

    fClient.println ("Begin communications with server...");

    // The socket connection was made by the caller, now
    // set up the streams and login to the server.
    try {
      if (!doConnection ()){
          fClient.println (" Connection/login failed");
          closeServer ();
          return;
      }
    }
    catch (IOException ioe) {
      fClient.println (" I/O exception with server:"+ ioe);
      return;
    }

    // Connection made so let parent SimClient know that
    fClient.setConnected ();

    // Obtain via the server the parameters that describe the simulated
    // experiment.
    if (!getSimExptParams ()) {
        closeServer ();
        return;
    }

    fClient.println ("Simulated experiment parameters read and installed.");

    int nVal = 0;

    // This loops until either the connection is broken or the
    // stop button or stop key is hit
    while (fKeepRunning) {
      // Pause here to wait for the parent to start the data
      // taking by invoking the startRun () method.
      waitForInstructions ();
      fClient.println (" Send the run setup...");

      // Send the run setup info to the server. This will
      // also initiate the start of the simulation.
      if (!sendRunSetup () ) break;

      fClient.println (" Successfully sent run setup.");
      fClient.println (" Now read drop data.");

      // Run started.  Now read data for each drop event
      while (true) {

         // Get a message from the server
        fServerCmd = readNetInputInt ();
        if (fFailedIO) {
            fClient.println (" Server read failed - receiving data");
            break;
        }
        // Either more data or end of run
        if (fServerCmd != SimUtil.EVENT_DATA) break;

        // Get more data
        nVal = readNetInputInt ();
        if (fFailedIO) {
            fClient.println (" Server read failed - array sizes");
            break;
        }

        // Read time measurements
        fData[0] = readNetInputDoubleArray (fData[0], nVal);
        if (fFailedIO) {
            fClient.println (" Server read failed - array 1");
            break;
        }

        // Read time measurements
        fData[1] = readNetInputDoubleArray (fData[1], nVal);
        if (fFailedIO) {
            fClient.println (" Server read failed - array 2");
            break;
        }

        // Pass drop data to parent for analysis
        fClient.setData (fData);
      }
      // All the drop events completed. Now do the
      // run analysis.
      fClient.runDone ();

      if (fFailedIO) break;
    }

    // Finished with this connection to the server simulation
    // so close everything and shut up shop.
    if (fServer != null) closeServer ();
    fClient.println ("disconnected");
    fClient.setDisconnected ();

  } // run

  /**
    *  Wait here until the parent invokes the
    *  startRun () method.
   **/
  synchronized void waitForInstructions () {
    // Wait for notifyAll in startRun method.
    try {
      wait ();
    }
    catch (Exception e) {}
  } // waitForInstructions

  /**
    *  Get the parameters for the simulated experiment.
    *  These will be used in the run analysis here.
   **/
  boolean getSimExptParams () {
    // Get the initialize command from the server
    fServerCmd = readNetInputInt ();
    if (fFailedIO){
        fClient.println (" Server read failed - command");
        return false;
    }

    if (fServerCmd != SimUtil.INIT) {
        fClient.println (" Did not receive INIT command from server. Break connection!");
        return false;
    }

    // Get the experiment parameters - top/bot y values, time range
    int nVal = readNetInputInt ();
    if (fFailedIO) {
        fClient.println (" Server read failed - array sizes");
        return false;
    }

    // Read time measurements
    fData[0] = readNetInputDoubleArray (fData[0], nVal);
    if (fFailedIO){
        fClient.println (" Server read failed - array 1");
        return false;
    }

    fClient.setExptParameters (fData[0]);
    return true;
  } // getSimExptParams

  /**
    *  Send the run setup information to the server
    *  in an integer array and a floating point array.
    *  This will initiate the start of the run simulation
    *  on the server.
   **/
  boolean sendRunSetup () {

    // Tell the server to begin the simulation process
    writeNetOutputInt (SimUtil.START);
    if (fFailedIO){
       fClient.println (" Server write failed - Start run");
       return false;
    }

    // Send the run setup data in two arrays. The setup values
    // include such items as the number of drops to simulate.

    // Start with the integer array size
    writeNetOutputInt (fISetup.length);
    if (fFailedIO){
        fClient.println (" Server write failed - setup array 1 size");
        return false;
    }

    // Send the array
    writeNetOutputIntArray (fISetup, fISetup.length);
    if ( fFailedIO){
        fClient.println (" Server write failed - setup array 1");
        return false;
    }

    // Start with the double array size
    writeNetOutputInt (fDSetup.length);
    if (fFailedIO){
        fClient.println (" Server write failed - setup array 2 size");
        return false;
    }

    // Send the array
    writeNetOutputDoubleArray (fDSetup, fDSetup.length);
    if (fFailedIO){
        fClient.println (" Server write failed - setup array 2");
        return false;
    }
    return true;
  } // sendRunSetup

  /**
    * The parent SimClient_JApplet11 invokes this when the
    * "Run Sim" button pushed. It will get the setup parameters
    * from the parent interface and with the invocation of
    * notifyAll () it will release the thread from the wait state.
    * This will start the simulation and transmission of the data
    * to here.
   **/
  public synchronized void startRun (int [] iData,
                                     double [] dData) {
    fISetup = iData;
    fDSetup = dData;
    notifyAll ();
    fClient.println (" Invoked startRun method");
  } // startRun

  /** Set up the streams with the server and then login. **/
  boolean doConnection () throws IOException {

    // Something wrong and server closed prematurely, causing reference
    // to be set to null
    if (fServer == null) {
        fClient.println (" Server prematurely closed.");
        return false;
    }

    // Get the input and output streams from the socket
    fNetInputStream = fServer.getInputStream ();

    // Use the reader for obtaining text
    fNetInputReader = new BufferedReader (
        new InputStreamReader ( fNetInputStream ) ) ;

    // User the DataInputStream for getting numerical values.
    fNetDataInputStream = new DataInputStream ( fNetInputStream );

    // Output stream for sending messages to the server.
    fNetOutputStream = fServer.getOutputStream ();

    // Get a data output stream for writing numerical data to the client
    fNetDataOutputStream = new DataOutputStream (fNetOutputStream);

    // Write with a PrintWriter for sending text to the server.
    fPrintWriter= new PrintWriter (
      new OutputStreamWriter (fNetDataOutputStream, "8859_1"), true );

    // Now try the login procedure.
    if (!login ()) return false;

    return true;

  } // doConnection

  /**
    * Here is a homemade login protocol. A password could
    * easily be added.
   **/
  boolean login () {
    fClient.println (" Waiting for login prompt...");

    String msg_line=readNetInputLine ();
    if (msg_line == null) return false;
    fClient.println (msg_line);
    if (!msg_line.startsWith ("Username:") ) return false;

    fClient.println (" Send username " + fUserName);
    writeNetOutputLine (fUserName);
    if (fFailedIO){
      fClient.println (" Error occurred in sending username!");
      return false;
    }

    fClient.println ("Waiting for response...");

    msg_line=readNetInputLine ();
    if (msg_line == null){
        fClient.println (" Error occurred in confirmation of login!");
        return false;
    }
    fClient.println (msg_line);

    return true;
  } // login

  /**
    * Do all of the steps needed to stop the connection.
    * This method can be invoked from the parent to kill
    * this worker and its server connection.
   **/
  public void finish () {
    // Kill the thread and stop the server
    fKeepRunning = false;
    closeServer ();
  } // finish

  /** Close the socket to the server. **/
  void closeServer () {
    fClient.println ("Close connection to server");
    fClient.setDisconnected ();
    if (fServer == null) return;
    try {
      fServer.close ();
      fServer = null;
    }
    catch (IOException e)
    {}
  } // closeServer

} // class SimClientWorker

 

Most recent update: Oct. 25, 2005

  
  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.