/* From http://java.sun.com/docs/books/tutorial/index.html */
/*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* -Redistribution of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* -Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
/*
* 1.1 version.
*/
import java.io.*;
import java.net.*;
import java.util.*;
class TalkServerThread extends Thread {
public Socket socket;
public BufferedReader is;
public BufferedWriter os;
TalkServer server;
boolean DEBUG = false;
public String toString() {
return "TalkServerThread: socket = " + socket
+ "; is = " + is
+ "; os = " + os;
}
TalkServerThread(Socket socket, TalkServer server) throws IOException {
super("TalkServer");
is = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
os = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()));
if (is == null) {
System.err.println("TalkServerThread: Input stream seemed "
+ "to be created successfully, but it's null.");
throw new IOException();
}
if (os == null) {
System.err.println("TalkServerThread: Output stream seemed "
+ "to be created successfully, but it's null.");
throw new IOException();
}
this.socket = socket;
this.server = server;
}
public void run() {
while (socket != null) {
try {
//Read data.
String str = is.readLine();
//Pass it on.
if (str != null) {
server.forwardString(str, this);
}
} catch (EOFException e) { //No more data on this socket...
server.forwardString("SERVER SAYS other applet disconnected",
this);
cleanup();
return;
} catch (NullPointerException e) { //Socket doesn't exist...
server.forwardString("SERVER SAYS no socket to other applet",
this);
cleanup();
return;
} catch (IOException e) { //Read problem..
server.forwardString("SERVER SAYS socket trouble with other applet",
this);
cleanup();
return;
} catch (Exception e) { //Unknown exception. Complain and quit.
System.err.println("Exception on is.readLine():");
e.printStackTrace();
cleanup();
return;
}
}
}
protected void finalize() {
cleanup();
}
void cleanup() {
try {
if (is != null) {
is.close();
is = null;
}
} catch (Exception e) {} //Ignore errors.
try {
if (os != null) {
os.close();
os = null;
}
} catch (Exception e) {} //Ignore errors.
try {
if (socket != null) {
socket.close();
socket = null;
}
} catch (Exception e) {} //Ignore errors.
}
}
/*
* 1.1 version.
*/
import java.net.*;
import java.io.*;
class TalkServer {
TalkServerThread[] tstList = new TalkServerThread[2];
boolean DEBUG = false;
public static void main(String[] args) {
new TalkServer().start();
}
public void start() {
ServerSocket serverRSocket = null;
int numConnected = 0;
try {
serverRSocket = new ServerSocket(0);
System.out.println("TalkServer listening on rendezvous port: "
+ serverRSocket.getLocalPort());
} catch (IOException e) {
System.err.println("Server could not create server socket for rendezvous.");
return;
}
while (true) {
//Connect to two clients.
while (numConnected < 2) {
TalkServerThread tst;
tst = connectToClient(serverRSocket);
if (tst != null) {
numConnected++;
if (tstList[0] == null) {
tstList[0] = tst;
} else {
tstList[1] = tst;
}
}
} //end while (numConnected < 2) loop
if (DEBUG) {
try {
System.out.println("tst #0 = " + tstList[0]);
} catch (Exception e) {}
try {
System.out.println("tst #1 = " + tstList[1]);
} catch (Exception e) {}
}
//If they're really OK, tell them to start writing.
if (everythingIsOK(0) & everythingIsOK(1)) {
for (int i = 0; i < 2; i++) {
writeToStream("START WRITING!\n----------------------"
+ "-------------", tstList[i].os);
}
} else {
System.err.println("2 server threads created, but "
+ "not everything is OK");
}
while (numConnected == 2) {
if (!everythingIsOK(0)) {
if (DEBUG) {
System.out.println("Applet #0 is hosed; disconnecting.");
}
numConnected--;
cleanup(tstList[0]);
tstList[0] = null;
}
if (!everythingIsOK(1)) {
if (DEBUG) {
System.out.println("Applet #1 is hosed; disconnecting.");
}
numConnected--;
cleanup(tstList[1]);
tstList[1] = null;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
} //end while(numConnected==2) loop
if (DEBUG) {
try {
System.out.println("Number of connections = " + numConnected);
System.out.println("tst #0 = " + tstList[0]);
System.out.println("tst #1 = " + tstList[1]);
} catch (Exception e) {}
}
} //end while (true) loop
}
protected TalkServerThread connectToClient(ServerSocket serverRSocket) {
Socket rendezvousSocket = null;
TalkServerThread tst = null;
//Listen for client connection on the rendezvous socket.
try {
rendezvousSocket = serverRSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
e.printStackTrace();
return null;
}
//Create a thread to handle this connection.
try {
tst = new TalkServerThread(rendezvousSocket, this);
tst.start();
} catch (Exception e) {
System.err.println("Couldn't create TalkServerThread:");
e.printStackTrace();
return null;
}
writeToStream("Successful connection. "
+ "Please wait for second applet to connect...",
tst.os);
return tst;
}
boolean everythingIsOK(int tstNum) {
TalkServerThread tst = tstList[tstNum];
if (tst == null) {
if (DEBUG) {
System.out.println("TalkServerThread #" + tstNum
+ " is null");
}
return false;
} else {
if (tst.os == null) {
if (DEBUG) {
System.out.println("TalkServerThread #" + tstNum
+ " output stream is null.");
}
return false;
}
if (tst.is == null) {
if (DEBUG) {
System.out.println("TalkServerThread #" + tstNum
+ " input stream is null.");
}
return false;
}
if (tst.socket == null) {
if (DEBUG) {
System.out.println("TalkServerThread #" + tstNum
+ " socket is null.");
}
return false;
}
}
return true;
}
void cleanup(TalkServerThread tst) {
if (tst != null) {
try {
if (tst.os != null) {
tst.os.close();
tst.os = null;
}
} catch (Exception e) {} //Ignore errors
try {
if (tst.is != null) {
tst.is.close();
tst.is = null;
}
} catch (Exception e) {} //Ignore errors
try {
if (tst.socket != null) {
tst.socket.close();
tst.socket = null;
}
} catch (Exception e) {} //Ignore errors
}
}
public void forwardString(String string, TalkServerThread requestor) {
BufferedWriter clientStream = null;
if (tstList[0] == requestor) {
if (tstList[1] != null) {
clientStream = tstList[1].os;
} else {
if (DEBUG) {
System.out.println("Applet #0 has a string to forward, "
+ "but Applet #1 is gone...");
}
return;
}
} else {
if (tstList[0] != null) {
clientStream = tstList[0].os;
} else {
if (DEBUG) {
System.out.println("Applet #1 has a string to forward, "
+ "but Applet #0 is gone...");
}
return;
}
}
if (clientStream != null) {
writeToStream(string, clientStream);
} else if (DEBUG) {
System.out.println("Can't forward string -- no output stream.");
}
}
public void writeToStream(String string, BufferedWriter stream) {
if (DEBUG) {
System.out.println("TalkServer about to forward data: "
+ string);
}
try {
stream.write(string);
stream.newLine();
stream.flush();
if (DEBUG) {
System.out.println("TalkServer forwarded string.");
}
} catch (IOException e) {
System.err.println("TalkServer failed to forward string:");
e.printStackTrace();
return;
} catch (NullPointerException e) {
System.err.println("TalkServer can't forward string "
+ "since output stream is null.");
return;
}
}
}
/*
* 1.1 version.
*/
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
public class TalkClientApplet extends Applet
implements Runnable,
ActionListener {
Socket socket;
BufferedWriter os;
BufferedReader is;
TextField portField, message;
TextArea display;
Button button;
int dataPort;
boolean trysted;
Thread receiveThread;
String host;
boolean DEBUG = false;
String newline;
public void init() {
//Get the address of the host we came from.
host = getCodeBase().getHost();
//Set up the UI.
GridBagLayout gridBag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridBag);
message = new TextField("");
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = GridBagConstraints.REMAINDER;
gridBag.setConstraints(message, c);
message.addActionListener(this);
add(message);
display = new TextArea(10, 40);
display.setEditable(false);
c.weightx = 1.0;
c.weighty = 1.0;
c.fill = GridBagConstraints.BOTH;
gridBag.setConstraints(display, c);
add(display);
Label l = new Label("Enter the port (on host " + host
+ ") to send the request to:",
Label.RIGHT);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 1;
c.weightx = 0.0;
c.weighty = 0.0;
gridBag.setConstraints(l, c);
add(l);
portField = new TextField(6);
c.fill = GridBagConstraints.NONE;
gridBag.setConstraints(portField, c);
portField.addActionListener(this);
add(portField);
button = new Button("Connect");
gridBag.setConstraints(button, c);
button.addActionListener(this);
add(button);
newline = System.getProperty("line.separator");
}
public synchronized void start() {
if (DEBUG) {
System.out.println("In start() method.");
}
if (receiveThread == null) {
trysted = false;
portField.setEditable(true);
button.setEnabled(true);
os = null;
is = null;
socket = null;
receiveThread = new Thread(this);
receiveThread.start();
if (DEBUG) {
System.out.println(" Just set everything to null and started thread.");
}
} else if (DEBUG) {
System.out.println(" receiveThread not null! Did nothing!");
}
}
public synchronized void stop() {
if (DEBUG) {
System.out.println("In stop() method.");
}
receiveThread = null;
trysted = false;
portField.setEditable(true);
button.setEnabled(true);
notify();
try { //Close input stream.
if (is != null) {
is.close();
is = null;
}
} catch (Exception e) {} //Ignore exceptions.
try { //Close output stream.
if (os != null) {
os.close();
os = null;
}
} catch (Exception e) {} //Ignore exceptions.
try { //Close socket.
if (socket != null) {
socket.close();
socket = null;
}
} catch (Exception e) {} //Ignore exceptions.
}
public Insets getInsets() {
return new Insets(4,4,5,5);
}
public void paint(Graphics g) {
Dimension d = getSize();
Color bg = getBackground();
g.setColor(bg);
g.draw3DRect(0, 0, d.width - 1, d.height - 1, true);
g.draw3DRect(3, 3, d.width - 7, d.height - 7, false);
}
public synchronized void actionPerformed(ActionEvent event) {
int port;
if (DEBUG) {
System.out.println("In action() method.");
}
if (receiveThread == null) {
start();
}
if (!trysted) {
//We need to attempt a rendezvous.
if (DEBUG) {
System.out.println(" trysted = false. "
+ "About to attempt a rendezvous.");
}
//Get the port the user entered...
try {
port = Integer.parseInt(portField.getText());
} catch (NumberFormatException e) {
//No integer entered.
display.append("Please enter an integer below."
+ newline);
return;
}
//...and rendezvous with it.
rendezvous(port);
} else { //We've already rendezvoused. Just send data over.
if (DEBUG) {
System.out.println(" trysted = true. "
+ "About to send data.");
}
String str = message.getText();
message.selectAll();
try {
os.write(str);
os.newLine();
os.flush();
} catch (IOException e) {
display.append("ERROR: Applet couldn't write to socket."
+ newline);
display.append("...Disconnecting."
+ newline);
stop();
return;
} catch (NullPointerException e) {
display.append("ERROR: No output stream!"
+ newline);
display.append("...Disconnecting."
+ newline);
stop();
return;
}
display.append("Sent: " + str + newline);
}
}
synchronized void waitForTryst() {
//Wait for notify() call from action().
try {
wait();
} catch (InterruptedException e) {}
if (DEBUG) {
System.out.println("waitForTryst about to return. "
+ "trysted = " + trysted + ".");
}
return;
}
public void run() {
String received = null;
waitForTryst();
//OK, now we can send messages.
while (Thread.currentThread() == receiveThread) {
try {
//Wait for data from the server.
received = is.readLine();
//Display it.
if (received != null) {
display.append("Received: " + received
+ newline);
} else { //success but no data...
System.err.println("End of stream?");
return; //XXX
}
} catch (IOException e) { //Perhaps a temporary problem?
display.append("NOTE: Couldn't read from socket.\n");
return;
}
}
}
private void rendezvous(int port) {
//Try to open a socket to the port.
try {
socket = new Socket(host, port);
} catch (UnknownHostException e) {
display.append("ERROR: Can't find host: " + host
+ newline);
return;
} catch (IOException e) {
display.append("ERROR: Can't open socket on rendezvous port "
+ port + " (on host " + host + ")."
+ newline);
return;
}
//Try to open streams to read and write from the socket.
try {
os = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()));
is = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
display.append("ERROR: Created data socket but can't "
+ "open stream on it."
+ newline);
display.append("...Disconnecting." + newline);
stop();
return;
}
if ((os != null) & (is != null)) {
if (DEBUG) {
System.out.println("Successful rendezvous.");
System.out.println("socket = " + socket);
System.out.println("output stream = " + os);
System.out.println("input stream = " + is);
}
//Let the main applet thread know we've successfully rendezvoused.
portField.setEditable(false);
button.setEnabled(false);
trysted = true;
notify();
} else {
display.append("ERROR: Port is valid but communication failed. "
+ "Please TRY AGAIN." + newline);
}
}
}
|