import java.io.*;
import java.net.*;
import java.util.*;
public class ChatServer
{ protected final static String CHATMASTER_ID="ChatMaster";
protected final static String SEP=":";
protected ServerSocket servSock;
protected ArrayList clients;
private static boolean DEBUG=false;
public static void main(String[] argv){
System.out.println("Chat Server 0.1 starting...");
if(argv.length==1&&argv[0].equals("-debug"))DEBUG=true;
ChatServer w=new ChatServer();
w.runServer();
System.out.println("**ERROR*Chat Server 0.1 quitting");
}
ChatServer(){
clients=new ArrayList();
try{ servSock=new ServerSocket(Chat.PORTNUM);
System.out.println("Chat Server Listening on port"+ Chat.PORTNUM);
}
catch(IOException e)
{ log("IO Exception in ChatServer.<init>");
System.exit(0);
}
}
public void runServer()
{ try{
while(true){
Socket us=servSock.accept();
String hostName=us.getInetAddress().getHostName();
System.out.println("Accepted from "+hostName);
ChatHandler c1=new ChatHandler(us,hostName);
synchronized(clients)
{ clients.add(c1);
c1.start();
if(clients.size()==1)c1.send(CHATMASTER_ID,"Welcome! you'er the first one here");
else{c1.send(CHATMASTER_ID,"Welcome! you're the latest of"+clients.size()+"users");
}
}
}
}catch(IOException e){
log("IO Exception in runServer:"+e);
System.exit(0);
}
}
protected void log(String s)
{ System.out.println(s);
}
protected class ChatHandler extends Thread{
protected Socket clientSock;
protected BufferedReader is;
protected PrintWriter pw;
protected String clientIP;
protected String login;
public ChatHandler(Socket sock,String clnt)throws IOException
{ clientSock=sock;
clientIP=clnt;
is=new BufferedReader(new InputStreamReader(sock.getInputStream()));
pw=new PrintWriter(sock.getOutputStream(),true);
}
public void run(){
String line;
try{ while((line=is.readLine())!=null){
char c=line.charAt(0);
line=line.substring(1);
switch(c){
case Chat.CMD_LOGIN:
if(!Chat.isValidLoginName(line)){
send(CHATMASTER_ID,"LOGIN"+line+"invalid");
log("LOGININVALID from"+clientIP);
continue;
}
login=line;
broadcast(CHATMASTER_ID,login+"joins us,for a total of"+clients.size()+"uses");
break;
case Chat.CMD_MESG:
if(login==null){
send(CHATMASTER_ID,"please login first");
continue;
}
int where=line.indexOf(Chat.SEPARATOR);
String recip=line.substring(0,where);
String mesg=line.substring(where+1);
log("MESG:"+login+"-->"+recip+":"+mesg);
ChatHandler c1=lookup(recip);
if(c1==null)psend(CHATMASTER_ID,"not logged in.");
else c1.psend(login,mesg);
break;
case Chat.CMD_QUIT:
broadcast(CHATMASTER_ID,"Goodbye to"+login+"@"+clientIP);
close();
return;
case Chat.CMD_BCAST:
if(login!=null)broadcast(login,line);
else log("B<L from"+clientIP);
break;
default: log("Unknown cmd"+"from"+login+"@"+clientIP);
}
}
}
catch(IOException e){log("IO Exception:"+e);}
finally{
System.out.println(login+SEP+"All Done");
synchronized(clients){
clients.remove(this);
if(clients.size()==0){System.out.println(CHATMASTER_ID+SEP+"Im so lonely I could cry...");}
else if(clients.size()==1){ChatHandler last=(ChatHandler)clients.get(0);
last.send(CHATMASTER_ID,"Hey,you're talking to yourself again");}
else {broadcast(CHATMASTER_ID,"There are now"+clients.size()+"users");
}
}
}
}
protected void close(){
if(clientSock==null){
log("close when not open");
return;
}
try{ clientSock.close();
clientSock=null;
}
catch(IOException e){log("Failure during close to"+clientIP);
}
}
public void send(String sender,String mesg){
pw.println(sender+SEP+mesg);
}
protected void psend(String sender,String msg){
send("<"+sender+"*>",msg);
}
public void broadcast(String sender,String mesg){
System.out.println("Broadcasting"+sender+SEP+mesg);
for(int i=0;i<clients.size();i++){
ChatHandler sib=(ChatHandler)clients.get(i);
if(DEBUG)System.out.println("Sending to "+sib);
sib.send(sender,mesg);}
if(DEBUG)System.out.println("Done broadcast");
}
protected ChatHandler lookup(String nick){
synchronized(clients){
for(int i=0;i<clients.size();i++){
ChatHandler c1=(ChatHandler)clients.get(i);
if(c1.login.equals(nick))return c1;
}
}
return null;
}
public String toString()
{ return "ChatHandler["+login+"]";
}
}
}