| Handler.java |
package SimpleChatOne;
// Fri Oct 15 18:07:43 EST 2004
//
// Written by Sean R. Owens, sean at guild dot net, released to the
// public domain. Share and enjoy. Since some people argue that it is
// impossible to release software to the public domain, you are also free
// to use this code under any version of the GPL, LPGL, or BSD licenses,
// or contact me for use of another license.
// http://darksleep.com/player
import java.net.Socket;
import java.net.ServerSocket;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
public class Handler implements Runnable {
private final static int READ_BUF_SIZE=1024;
private final static int SAVE_BUF_SIZE=10240;
private Socket sock = null;
private Switchboard switchboard = null;
private InputStream sockInput = null;
private OutputStream sockOutput = null;
private Thread myThread = null;
private byte[] bufferedData = null; // This is where we keep bytes we've read until we get a \n
private boolean loggedIn = false;
private String name="NotLoggedIn";
public String getName() { return name; }
public Handler(Socket sock, Switchboard switchboard, String messageOfTheDay) throws IOException {
this.sock = sock;
this.switchboard = switchboard;
sockInput = sock.getInputStream();
sockOutput = sock.getOutputStream();
bufferedData = new byte[SAVE_BUF_SIZE];
name = sock.getRemoteSocketAddress().toString();
myThread = new Thread(this);
try {
sockOutput.write(messageOfTheDay.getBytes(), 0, messageOfTheDay.getBytes().length);
// This call to flush() is optional - we're saying go
// ahead and send the data now instead of buffering
// it.
sockOutput.flush();
}
catch (IOException e) {
}
// Note that if we call myThread.start() now, we run the risk
// of this new thread calling run before we're finished
// constructing. We can't count on the fact that we call
// .start() last - javac or the jvm might have reordered the
// above lines. The class constructing us must wait for the
// constructor to return and then call start() on us.
System.out.println(this.getClass().getName()+": New handler created.");
}
public void start() {
myThread.start();
}
public synchronized void write(byte[] data, int numBytesRead) {
try {
sockOutput.write(data, 0, numBytesRead);
// This call to flush() is optional - we're saying go
// ahead and send the data now instead of buffering
// it.
sockOutput.flush();
}
catch (IOException e){
try {
System.err.println(this.getClass().getName()+": Error writing to socket, closing socket.");
sock.close();
}
catch (Exception e2){
System.err.println(this.getClass().getName()+": Exception while closing socket, e2="+e2);
e.printStackTrace(System.err);
}
switchboard.remove(this);
}
}
// This method is responsible for processing the bytes we've read.
// In the interest of clarity, it is not using the most efficient
// approach. In particular, it is not trying to be to clever to
// avoid copying the data around.
public void process(byte[] data, int numBytes) {
// For this version of SimpleChat, all we're going to do is
// forward data onto the other chatters.
switchboard.sendToAllConnections(this, data, numBytes);
}
// All this method does is wait for some bytes from the
// connection, read them, then write them back again, until the
// socket is closed from the other side.
public void run() {
System.out.println(this.getClass().getName()+": Handler run() starting.");
byte[] buf = new byte[READ_BUF_SIZE];
while(true) {
int numBytesRead = 0;
try {
// This call to read() will wait forever, until the
// program on the other side either sends some data,
// or closes the socket.
numBytesRead = sockInput.read(buf, 0, buf.length);
if(numBytesRead < 0) {
System.err.println(this.getClass().getName()+": Tried to read from socket, read() returned < 0, Closing socket.");
break;
}
System.err.println(this.getClass().getName()+": Received "+numBytesRead+" bytes, sending to other clients: "+new String(buf));
process(buf, numBytesRead);
}
catch (Exception e){
e.printStackTrace(System.err);
break;
}
}
try {
System.err.println(this.getClass().getName()+":Closing socket.");
sock.close();
}
catch (Exception e) {
System.err.println(this.getClass().getName()+":Exception while closing socket, e="+e);
e.printStackTrace(System.err);
}
switchboard.remove(this);
}
}