import java.io.*;
import java.net.*;
public class ims {
public static server me;
public static String name;
//sets up getting your ip, name and creates the server object
//loops thorugh until you type ".exit"
public static void main(String args[]){
InetAddress yours = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try {
yours = InetAddress.getLocalHost();
}
catch(UnknownHostException e){
System.out.println("Error finding your IP.");
return;
}
System.out.println("Your IP Address: "+yours.getHostAddress());
String input = "";
System.out.print("Enter Your Name: ");
name = "";
try {
name = in.readLine();
}
catch(IOException e) {
System.out.println("Error reading name.");
return;
}
System.out.println("Welcome "+name);
System.out.println("Initializing server...");
me = new server(name);
System.out.println("Server initiated.");
while(!input.equals(".exit")){
try {
input = in.readLine();
}
catch(IOException e){
System.out.println("Error reading input.");
break;
}
if(input.length()>0) {
if(input.charAt(0)=='.') handleCommand(input);
else me.send(name+": "+input);
}
}
send("Server Disconnected.");
me.close();
}
//static member for sending output to everyone on server
public static void send(String output){
me.send(output);
}
//static member for a leaving client
public static void leave(String name){
me.leave(name);
}
//lists the clients to the selected receiver
public static void list(PrintWriter receiver){
me.list(receiver);
}
public static void message(PrintWriter sender, String sendername, String receiver, String message){
me.message(sender,sendername,receiver,message);
}
//handles a command (starts with '.')
public static void handleCommand(String input){
if(input.equals(".list")) {
me.list(new PrintWriter(System.out,true));
return;
}
try {
int spaceindex = input.indexOf(" ");
int nextspaceindex = input.indexOf(" ",spaceindex+1);
if(spaceindex+1<input.length()&&spaceindex>0){
String command = input.substring(1,spaceindex);
String param;
if(command.equals("kick")) {
param = input.substring(spaceindex+1);
me.kick(param);
return;
}
if(command.equals("message")) {
String message = input.substring(nextspaceindex+1);
param = input.substring(spaceindex+1,nextspaceindex);
me.message(new PrintWriter(System.out, true), name, param, message);
return;
}
}
}
catch(Exception e) {}
System.out.println("Invalid Command.");
}
}
class server implements Runnable{
private ServerSocket theServer;
private client[] clients;
private int clientnumber;
private int clientmax;
private String hostname;
private Thread listener;
public boolean running;
//initializes the server with max of 16 clients on port 45654
//starts the thread for listening for accepts
public server(String name){
hostname = name;
clientnumber = 0;
clientmax = 16;
clients = new client[16];
try {
theServer = new ServerSocket(45654);
}
catch(IOException e){
System.out.println("Error creating server.");
System.exit(-1);
}
running = true;
listener = new Thread(this);
listener.start();
}
//listens for people wanting to join, and accepts/creates a client for them
public void run(){
client temp;
while(running){
try {
if(clientnumber<clientmax) {
temp = new client(theServer.accept());
clients[clientnumber++] = temp;
}
else return;
}
catch(IOException e){
if(running) System.out.println("Invalid client output caught.");
}
}
}
//sends output to every client and prints it on server's screen
public void send(String output){
int i;
for(i=0;i<clientnumber;i++) clients[i].write(output);
System.out.println(output);
}
//loops through the clients finding the person to kick based on name
//then kicks the person and stops their thread and outputs kick message
public void kick(String booted){
int i;
for(i=0;i<clientnumber;i++){
if(clients[i].name.equalsIgnoreCase(booted)){
clients[i].write("You have been kicked!");
clients[i].close();
ims.send(booted+" was kicked!");
return;
}
}
System.out.println("Could not find "+booted+".");
}
//loops through to find the leaver and closes him/posts message that he left
public void leave(String leaver){
int i;
for(i=0;i<clientnumber;i++){
if(clients[i].name.equalsIgnoreCase(leaver)){
ims.send(leaver+" has left the chat.");
clients[i].close();
clientnumber--;
for(;i<clientnumber;i++) clients[i] = clients[i+1];
return;
}
}
}
//sends a message to the selected user, also displaying it on the senders screen
public void message(PrintWriter sender, String sendername, String receivername, String message){
if(receivername.equalsIgnoreCase(hostname)) {
System.out.println(sendername+" whispers: "+message);
sender.println("You whisper to "+receivername+": "+message);
return;
}
else for(int i=0;i<clientnumber;i++) if(clients[i].name.equalsIgnoreCase(receivername)){
clients[i].write(sendername+" whispers: "+message);
sender.println("You whisper to "+receivername+": "+message);
return;
}
sender.println("Could not find "+receivername+".");
}
//gets a list of all the users in the channel and sends the message across the printwriter
public void list(PrintWriter receiver){
String list = "Users in channel: "+hostname;
for(int i=0;i<clientnumber;i++) list += ", "+clients[i].name;
receiver.println(list);
}
//closes all of the cliients and stops this thread and closes the socket
public void close(){
int i;
int j = clientnumber;
running = false;
for(i=0;i<j;i++) clients[i].close();
try {
theServer.close();
}
catch(IOException e){
System.out.println("Error closing server.");
}
}
}
class client implements Runnable{
private Socket cSocket;
private PrintWriter sOut;
private BufferedReader sIn;
private Thread clientThread;
public String name;
public boolean running;
//creates the output and input based on the given socket for a client
//then sends to the server join message and starts thread for getting messages
public client(Socket s){
cSocket = s;
try {
sOut = new PrintWriter(cSocket.getOutputStream(),true);
sIn = new BufferedReader(new InputStreamReader(
cSocket.getInputStream()));
name = sIn.readLine();
}
catch(IOException e){
System.out.println("Error getting I/O for client.");
return;
}
ims.send(name+" has entered the chat.");
running = true;
clientThread = new Thread(this);
clientThread.start();
}
//loops through getting messages and sending them to everyone else
public void run(){
String input;
while(running){
input = read();
if(input==null||!running||input.equals(".exit")) break;
else if(input.length()>0&&input.charAt(0)=='.') handleCommand(input);
else ims.send(name+": "+input);
}
ims.leave(name);
}
//reads a line of text from the input
public String read(){
String input = null;
try {
input = sIn.readLine();
}
catch(IOException e) {
if(running) System.out.println("Error reading from client.");
}
return input;
}
//writes a line of output to the client
public void write(String output){
if(running) sOut.println(output);
}
//closes the sockets/input/output and stops the thread
public void close(){
running = false;
try {
sOut.close();
sIn.close();
cSocket.close();
}
catch(IOException e){
System.out.println("Error closing client.");
}
}
//handles a command (starts with '.')
public void handleCommand(String input){
if(input.equals(".list")) {
ims.list(sOut);
return;
}
try {
int spaceindex = input.indexOf(" ");
int nextspaceindex = input.indexOf(" ",spaceindex+1);
if(spaceindex+1<input.length()&&spaceindex>0){
String command = input.substring(1,spaceindex);
String param;
if(command.equals("message")) {
String message = input.substring(nextspaceindex+1);
param = input.substring(spaceindex+1,nextspaceindex);
ims.message(sOut, name, param, message);
return;
}
}
}
catch(Exception e){}
write("Invalid Command.");
}
}