|
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
|
|
|