diff --git a/ClientServerFramework/Client.class b/ClientServerFramework/Client.class new file mode 100644 index 0000000..6336b68 Binary files /dev/null and b/ClientServerFramework/Client.class differ diff --git a/ClientServerFramework/Client.java b/ClientServerFramework/Client.java new file mode 100644 index 0000000..02ccbff --- /dev/null +++ b/ClientServerFramework/Client.java @@ -0,0 +1,120 @@ +/** + * Created by danielbardin on 4/6/15. + */ + +import java.net.*; +import java.io.*; + +public class Client implements Runnable +{ + private Socket socket = null; + private Thread thread = null; + private DataInputStream userConsole = null; + private DataOutputStream outputStream = null; + private ClientThread client = null; + + + /* + Create client object + */ + public Client(String serverName, int serverPort) + { + System.out.println("Connecting to server host: " + serverName + " at port: " + serverPort); + try + { + socket = new Socket(serverName, serverPort); + System.out.println("Connected: " + socket); + start(); + } + catch (UnknownHostException e) + { + System.out.println("Host unknown: " + e.getMessage()); + } + catch (IOException e) + { + System.out.println("Unexpected exception: " + e.getMessage()); + } + } + + /* + create a new client thread + */ + public void run() + { + while (thread != null) { + try { + outputStream.writeUTF(userConsole.readLine()); + outputStream.flush(); + } catch (IOException e) { + System.out.println("Sending error: " + e.getMessage()); + stop(); + } + } + } + + + /* + method for a client to send a message + */ + public void sendMessage(String message) + { + if (message.equals("logmeout")) { + System.out.println("logmeout recognized. Press RETURN to exit."); + stop(); + } + else + System.out.println(message); + } + + /* + initialize a client thread + */ + public void start() throws IOException + { + userConsole = new DataInputStream(System.in); + outputStream = new DataOutputStream(socket.getOutputStream()); + + if (thread == null) + { + client = new ClientThread(this, socket); + thread = new Thread(this); + thread.start(); + } + } + + /* + Log out a client thread, shut down connections, close streams + */ + public void stop() + { + if (thread != null) { + thread.interrupt(); + thread = null; + } + + try + { + if (userConsole != null) + userConsole.close(); + if (outputStream != null) + outputStream.close(); + if (socket != null) + socket.close(); + } + catch (IOException e) + { + System.out.println("Error closing client process. Error message: " + e); + } + client.close(); + client.interrupt(); + } + + public static void main(String args[]) + { + Client client = null; + if (args.length != 2) + System.out.println("Usage: java Client host port"); + else + client = new Client(args[0], Integer.parseInt(args[1])); + } +} diff --git a/ClientServerFramework/ClientThread.class b/ClientServerFramework/ClientThread.class new file mode 100644 index 0000000..05117c0 Binary files /dev/null and b/ClientServerFramework/ClientThread.class differ diff --git a/ClientServerFramework/ClientThread.java b/ClientServerFramework/ClientThread.java new file mode 100644 index 0000000..98278f9 --- /dev/null +++ b/ClientServerFramework/ClientThread.java @@ -0,0 +1,62 @@ +/** + * Created by danielbardin on 4/6/15. + */ + +import java.net.*; +import java.io.*; + +public class ClientThread extends Thread +{ + + private Socket socket = null; + private Client client = null; + //private BufferedReader inputBuffer = null; + private DataInputStream inputStream = null; + + public ClientThread(Client client, Socket socket) + { + this.client = client; + this.socket = socket; + open(); + start(); + } + + /* + Connects this client via socket and creates a input reader + */ + public void open() + { + try { + inputStream = new DataInputStream(socket.getInputStream()); + } catch (IOException e) { + System.out.println("Error getting input stream: " + e); + client.stop(); + } + } + + public void close() + { + try { + if (inputStream != null) + inputStream.close(); + } + catch (IOException e) { + System.out.println("Error closing input stream: " + e); + } + } + + /* + Listener for client in infinite loop. Terminates when "logmeoff" read by server during message send + */ + public void run() + { + while (true) { + try { + client.sendMessage(inputStream.readUTF()); + } catch (IOException e) { + System.out.println("Listening error: " + e.getMessage()); + client.stop(); + } + } + } +} diff --git a/ClientServerFramework/Server.java b/ClientServerFramework/Server.java new file mode 100644 index 0000000..c8dab1e --- /dev/null +++ b/ClientServerFramework/Server.java @@ -0,0 +1,184 @@ +/** + * Created by danielbardin on 4/6/15. + */ + +import java.net.*; +import java.io.*; +import java.util.ArrayList; + +/* + Class to implement the server-side functionality and main method for a chat service + */ +public class Server implements Runnable +{ + // ArrayList of client/thread objects + private ArrayList clients = new ArrayList(); + + // This server's socket + private ServerSocket server = null; + + // This server's main thread; + private Thread thread = null; + + // How many clients are on this channel + private int numClients = 0; + + // Maximum number of clients allowed on this server + private static final int MAX_CLIENTS = 25; + + + /* + Constructor + */ + public Server(int port) + { + try { + // Prompt user of port connection attempt + System.out.println("Trying to connect to port: " + port); + + // make the connection to the port on our server + server = new ServerSocket(port); + + // prompt user of connection success. + System.out.println("Connection successful."); + + // start up the client + start(); + + } catch (IOException e) { + // Problem connecting + System.out.println("Could not attach to port: " + port + " The error was: " + e.getMessage()); + } + } + + /* + Start up + */ + public void run() + { + while (thread != null) { + try { + System.out.println("Waiting for first client connection. "); + addClient(server.accept()); + } catch (IOException e) { + System.out.println("Server run() error: " + e); + } + } + } + + + /* + Activate client thread + */ + public void start() + { + if (thread == null) { + thread = new Thread(this); + thread.start(); + } + } + +// /* +// Terminate client thread +// */ +// public void interrupt() +// { +// if (!thread.isInterrupted()) { +// thread.interrupt(); +// thread = null; +// } +// } + + /* + Find the client attempting to connect + */ + private int findClient(int id) + { + for (int i = 0; i < numClients; i++) { + if (clients.get(i).getId() == id) + return i; + } + return -1; + } + + + /* + Post a message to all users in this channel(i.e., host@port) from this id + */ + public synchronized void sendMessage(int id, String message) + { + // logmeout phrase will exit a person from the channel + if (message.equals("logmeout")) { + logoff(id); + } + else { + // Loops the clients array and posts the message to each. + for (ServerThread st : clients) { + st.sendMessage(id + ": " + message); + } + } + } + + + /* + Remove a user from the active roster and close their connection + */ + public synchronized void logoff(int id) + { + int clientsArrPos = findClient(id); + + if (clients.get(clientsArrPos).getId() == id) { + + numClients--; + + try { + clients.get(clientsArrPos).close(); + clients.remove(clientsArrPos); + } + catch (IOException e) { + System.out.println("Failed to log client off. Error message: " + e); + } + } + } + + + /* + Add a client thread to the server + */ + private void addClient(Socket socket) + { + // make sure clients is < 25 connections + if (numClients < MAX_CLIENTS) { + System.out.println("Client socket connection valid: " + socket); + + // Add a client thread to clients roster of active users. + clients.add(new ServerThread(this, socket)); + + try { + clients.get(numClients).open(); + clients.get(numClients).start(); + numClients++; + } + catch (IOException e) { + System.out.println("Error opening client thread: " + e); + clients.remove(clients.size()-1); + } + } + else { + System.out.println("Sorry, this channel is full."); + } + } + + /* + MAIN METHOD + */ + public static void main(String args[]) + { + Server server = null; + + if (args.length != 1) + System.out.println("Usage: java Server port"); + else + server = new Server(Integer.parseInt(args[0])); + } +} diff --git a/ClientServerFramework/ServerThread.java b/ClientServerFramework/ServerThread.java new file mode 100644 index 0000000..cdfa5e4 --- /dev/null +++ b/ClientServerFramework/ServerThread.java @@ -0,0 +1,107 @@ +/** + * Created by danielbardin on 4/6/15. + */ + +import java.net.*; +import java.io.*; + + +/* + Class for a server-side thread interface + */ +public class ServerThread extends Thread +{ + private Server server = null; + private Socket socket = null; + private int id = -1; + private DataInputStream inputStream = null; + private DataOutputStream outputStream = null; + + + /* + Constructor for the master server thread, calls the Thread superclass library , then initializes. + + A client thread can interface with the server, and other clients through this class. + */ + public ServerThread(Server server, Socket socket) + { + super(); + this.server = server; + this.socket = socket; + id = socket.getPort(); + } + + /* + Method for server thread to send message + */ + public void sendMessage(String message) + { + try + { + outputStream.writeUTF(message); + outputStream.flush(); + } + catch (IOException e) + { + System.out.println("Error sending message from user: " + id + "Error is: " + e.getMessage()); + + // If there is an send error, likely the socket failed, + // remove the user and kill their thread. + server.logoff(id); + interrupt(); + } + } + + /* + getter for thread ID + */ + public long getId() + { + return id; + } + + /* + Infinite "listener." Will keep listening and sending messages + */ + public void run() + { + System.out.println("ServerThread: " + id + " is running."); + + while (true) { + try + { + server.sendMessage(id, inputStream.readUTF()); + } + catch (IOException e) + { + System.out.println(id + " Error reading: " + e.getMessage()); + server.logoff(id); + interrupt(); + } + } + } + + /* + Initialize and open the input buffer and output stream(s) + */ + public void open() throws IOException + { + inputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream())); + outputStream = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); + } + + /* + Close out socket, input & output + */ + public void close() throws IOException + { + if (socket != null) + socket.close(); + if (inputStream != null) + inputStream.close(); + if (outputStream != null) + outputStream.close(); + } + + +}