From 979c1dc49f47d05fa2fd54f6a25e40a6f4c1792c Mon Sep 17 00:00:00 2001 From: Loki <Loki@Desktop-Loki> Date: Tue, 4 Aug 2020 15:09:19 -0700 Subject: [PATCH] Initial commit of the homework #2 Bernd 08/04/2020 --- .../Weissenberger/LokiChatClient.java | 107 +++++++++++++ .../Weissenberger/LokiChatServer.java | 149 ++++++++++++++++++ .../Weissenberger/LokiClientThread.java | 67 ++++++++ .../Weissenberger/LokiServerThread.java | 97 ++++++++++++ .../homework2/Weissenberger/README.md | 12 ++ 5 files changed, 432 insertions(+) create mode 100644 assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiChatClient.java create mode 100644 assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiChatServer.java create mode 100644 assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiClientThread.java create mode 100644 assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiServerThread.java diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiChatClient.java b/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiChatClient.java new file mode 100644 index 0000000000..4c133b53fb --- /dev/null +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiChatClient.java @@ -0,0 +1,107 @@ +package MV3500Cohort2020JulySeptember.homework2.Weissenberger; + +import java.io.*; +import java.net.*; + +/** + * This client program establishes a socket connection to the chat server, hand + * over the connection to a thread. + * + * @author Bernd "Loki" Weissenberger + */ +public class LokiChatClient implements Runnable { + + private Socket socket = null; + private Thread thread = null; + private DataInputStream console = null; + private DataOutputStream streamOut = null; + private LokiClientThread client = null; + + /** + * constructor. + * @param serverName as named (localhost per default) + * @param serverPort as named (should be 2317) + */ + public LokiChatClient(String serverName, int serverPort) { + System.out.println("***********************************************"); + System.out.println("* Establishing connection. Please wait ... :) *"); + System.out.println("***********************************************"); + + try { + socket = new Socket(serverName, serverPort); + System.out.println("I'm connected: " + socket); + start(); + } catch (UnknownHostException uhe) { + System.out.println("Host unknown: " + uhe.getMessage()); + } catch (IOException ioe) { + System.out.println("Unexpected exception (server isn't up??): " + ioe.getMessage()); + } + } + + public void run() { + while (thread != null) { + try { + streamOut.writeUTF(console.readLine()); + streamOut.flush(); + } catch (IOException ioe) { + System.out.println("Sending error: " + ioe.getMessage()); + stop(); + } + } + } + + public void handle(String msg) { + if (msg.equals(".bye")) { + System.out.println("Good bye. Press RETURN to exit ..."); + stop(); + } else { + System.out.println(msg); + } + } + + /** + * setup the streams and (if possible) the Thread + * @throws IOException + */ + public void start() throws IOException { + console = new DataInputStream(System.in); + streamOut = new DataOutputStream(socket.getOutputStream()); + if (thread == null) { + client = new LokiClientThread(this, socket); + thread = new Thread(this); + thread.start(); + } + } + + /** + * stops the Thread + */ + public void stop() { + if (thread != null) { //thread.stop(); + thread = null; + } + try { + if (console != null) { + console.close(); + } + if (streamOut != null) { + streamOut.close(); + } + if (socket != null) { + socket.close(); + } + } catch (IOException ioe) { + System.out.println("Error closing ..."); + } + client.close(); + } + + /** + * main method with fix IP and Port + * @param args + */ + public static void main(String args[]) { + LokiChatClient client = null; + client = new LokiChatClient("127.0.0.1", 2317); + } +} diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiChatServer.java b/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiChatServer.java new file mode 100644 index 0000000000..393d40bd92 --- /dev/null +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiChatServer.java @@ -0,0 +1,149 @@ +package MV3500Cohort2020JulySeptember.homework2.Weissenberger; + +import java.io.*; +import java.net.*; + +/** + * A server example that creates a new thread to handle multiple + * connections one after another, running in parallel. + * + * @author Bernd Weissenberger + */ +public class LokiChatServer implements Runnable { + + private LokiServerThread clients[] = new LokiServerThread[50]; + private ServerSocket server = null; + private Thread thread = null; + private int clientCount = 0; + + /** + * constructor + * @param port + */ + public LokiChatServer(int port) { + try { + System.out.println("Binding to port " + port + ", please wait ..."); + server = new ServerSocket(port); + System.out.println("Server started: " + server); + start(); + } catch (IOException ioe) { + System.out.println("Can not bind to port " + port + ": " + ioe.getMessage()); + } + } + + /** + * start a new thread + */ + @Override + public void run() { + while (thread != null) { + try { + System.out.println("Waiting for a client ..."); + addThread(server.accept()); + } catch (IOException ioe) { + System.out.println("Server accept error: " + ioe); + stop(); + } + } + } + public void start() { + if (thread == null) { + thread = new Thread(this); + thread.start(); + } + } + + /** + * kill the thread + */ + public void stop() { + if (thread != null) { + //thread.stop(); + thread = null; + } + } + + /** + * get the client by ID + * @param ID + * @return + */ + private int findClient(int ID) { + for (int i = 0; i < clientCount; i++) { + if (clients[i].getID() == ID) { + return i; + } + } + return -1; + } + + /** + * sending message to all clients + * @param ID + * @param input + */ + public synchronized void handle(int ID, String input) { + if (input.equals(".bye")) { + clients[findClient(ID)].send(".bye"); + remove(ID); + } else { + for (int i = 0; i < clientCount; i++) { + clients[i].send(ID + " says: " + input); + } + } + } + + /** + * remove a quit client from list + * @param ID + */ + public synchronized void remove(int ID) { + int pos = findClient(ID); + if (pos >= 0) { + LokiServerThread toTerminate = clients[pos]; + System.out.println("Removing client thread " + ID + " at " + pos); + if (pos < clientCount - 1) { + for (int i = pos + 1; i < clientCount; i++) { + clients[i - 1] = clients[i]; + } + } + clientCount--; + try { + toTerminate.close(); + } catch (IOException ioe) { + System.out.println("Error closing thread: " + ioe); + } + //toTerminate.stop(); + } + } + + /** + * add a thread to list + * @param socket + */ + private void addThread(Socket socket) { + if (clientCount < clients.length) { + System.out.println("Client accepted: " + socket); + clients[clientCount] = new LokiServerThread(this, socket); + try { + clients[clientCount].open(); + clients[clientCount].start(); + clientCount++; + } catch (IOException ioe) { + System.out.println("Error opening thread: " + ioe); + } + } else { + System.out.println("Client refused: maximum " + clients.length + " reached."); + } + } + + /** + * the main for this class. Just starts a new server listening at port 2317 + * @param args + */ + public static void main(String args[]) { + LokiChatServer server = null; + server = new LokiChatServer(2317); + } + +} diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiClientThread.java b/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiClientThread.java new file mode 100644 index 0000000000..7c17ba9e04 --- /dev/null +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiClientThread.java @@ -0,0 +1,67 @@ +package MV3500Cohort2020JulySeptember.homework2.Weissenberger; + +import java.io.*; +import java.net.*; + +/** + * A program that handles all logic associated with one socket connection by + * running in a thread of its own. This is the client portion. + * + * @author Bernd Weisenberger + */ +public class LokiClientThread extends Thread { + + private Socket socket = null; + private LokiChatClient client = null; + private DataInputStream streamIn = null; + + /** + * constructor + * @param client + * @param socket + */ + public LokiClientThread(LokiChatClient client, Socket socket) { + this.client = client; + this.socket = socket; + this.open(); + this.start(); + } + + /** + * initialize the stream + */ + public void open() { + try { + streamIn = new DataInputStream(socket.getInputStream()); + } catch (IOException ioe) { + System.out.println("Error getting input stream: " + ioe); + } + } + + /** + * closes the stream + */ + public void close() { + try { + if (streamIn != null) { + streamIn.close(); + } + } catch (IOException ioe) { + System.out.println("Error closing input stream: " + ioe); + } + } + + /** + * uses the handle() from Client to react (send or quit) + */ + public void run() { + while (true) { + try { + client.handle(streamIn.readUTF()); + } catch (IOException ioe) { + System.out.println("Listening error: " + ioe.getMessage()); + client.stop(); + } + } + } +} diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiServerThread.java b/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiServerThread.java new file mode 100644 index 0000000000..a8dfc011f0 --- /dev/null +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/LokiServerThread.java @@ -0,0 +1,97 @@ +package MV3500Cohort2020JulySeptember.homework2.Weissenberger; + +import java.io.*; +import java.net.*; + +/** + * A program that handles all logic associated with one socket connection + * by running in a thread of its own. This is the server + * portion + * + * @author Bernd Weissenberger + */ +public class LokiServerThread extends Thread { + + // as named + private LokiChatServer server = null; + private Socket socket = null; + private int ID = -1; + private DataInputStream streamIn = null; + private DataOutputStream streamOut = null; + + /** + * constructor + * @param server instance of the server + * @param socket ...and the socket + */ + public LokiServerThread(LokiChatServer server, Socket socket) { + super(); + this.server = server; + this.socket = socket; + this.ID = socket.getPort(); + } + + /** + * send the messages + * @param msg + */ + public void send(String msg) { + try { + streamOut.writeUTF(msg); + streamOut.flush(); + } catch (IOException ioe) { + System.out.println(ID + " ERROR sending: " + ioe.getMessage()); + server.remove(ID); + } + } + + /** + * simple getter + * @return + */ + public int getID() { + return ID; + } + + /** + * read he input using the handler method + */ + @Override + public void run() { + System.out.println("Server Thread " + ID + " running."); + while (true) { + try { + server.handle(ID, streamIn.readUTF()); + } catch (IOException ioe) { + System.out.println(ID + " ERROR reading: " + ioe.getMessage()); + server.remove(ID); + //stop(); + } + } + } + + /** + * open all needed streams + * @throws IOException + */ + public void open() throws IOException { + streamIn = new DataInputStream(new BufferedInputStream(socket.getInputStream())); + streamOut = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); + } + + /** + * close socket and streams + * @throws IOException + */ + public void close() throws IOException { + if (socket != null) { + socket.close(); + } + if (streamIn != null) { + streamIn.close(); + } + if (streamOut != null) { + streamOut.close(); + } + } +} diff --git a/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/README.md b/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/README.md index 0144d62d03..abb3a6f442 100644 --- a/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/README.md +++ b/assignments/src/MV3500Cohort2020JulySeptember/homework2/Weissenberger/README.md @@ -10,3 +10,15 @@ References include * [assignments source subdirectories](../../../../../assignments/src) show examples from previous cohorts. Questions and innovation are always welcome, good luck! + + +Coded three classes: +LokiChatServer +LokiServerThread +LokiChatClient +LokiClientThread + +1. Run the LokiChatServer once +2. Run the LokiChatClient twice or more +3. type some messages in a client console +4. you will see the message on each of the client consoles -- GitLab