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