From a6675cf753d2ac52ab98ab8474f639f5c49d21d5 Mon Sep 17 00:00:00 2001 From: art Date: Fri, 12 Oct 2018 18:18:52 +0500 Subject: [PATCH 01/12] Add client code for connection to a chat server --- src/chat/Client.java | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/chat/Client.java b/src/chat/Client.java index ecc8d88..7cc7da4 100644 --- a/src/chat/Client.java +++ b/src/chat/Client.java @@ -1,7 +1,25 @@ package chat; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.net.InetAddress; +import java.net.Socket; +import java.util.logging.Level; +import java.util.logging.Logger; + public class Client { + private static final Logger LOGGER = Logger.getLogger(Client.class.getName()); + + private final static String CHAT_SERVER_ADDRESS = "127.0.0.1"; + private final static int CHAT_SERVER_PORT = 23456; + public static void main(String[] args) throws Exception { - System.out.println("Client started!"); + try { + final Socket socket = new Socket(InetAddress.getByName(CHAT_SERVER_ADDRESS), CHAT_SERVER_PORT); + final DataInputStream input = new DataInputStream(socket.getInputStream()); + final DataOutputStream output = new DataOutputStream(socket.getOutputStream()); + } catch (Exception e) { + LOGGER.log(Level.SEVERE, String.format("Cannot connect to %s on port %d", CHAT_SERVER_ADDRESS, CHAT_SERVER_PORT)); + } } } \ No newline at end of file From e8ee66c34157e3a70a2f55ce74ce1041503af00e Mon Sep 17 00:00:00 2001 From: art Date: Fri, 12 Oct 2018 18:29:08 +0500 Subject: [PATCH 02/12] Add server-side code --- src/chat/Client.java | 2 +- src/chat/Server.java | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/chat/Client.java b/src/chat/Client.java index 7cc7da4..0c762d5 100644 --- a/src/chat/Client.java +++ b/src/chat/Client.java @@ -13,7 +13,7 @@ public class Client { private final static String CHAT_SERVER_ADDRESS = "127.0.0.1"; private final static int CHAT_SERVER_PORT = 23456; - public static void main(String[] args) throws Exception { + public static void main(String[] args) { try { final Socket socket = new Socket(InetAddress.getByName(CHAT_SERVER_ADDRESS), CHAT_SERVER_PORT); final DataInputStream input = new DataInputStream(socket.getInputStream()); diff --git a/src/chat/Server.java b/src/chat/Server.java index cd56e71..622c133 100644 --- a/src/chat/Server.java +++ b/src/chat/Server.java @@ -1,7 +1,23 @@ package chat; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.logging.Level; +import java.util.logging.Logger; + public class Server { - public static void main(String[] args) throws Exception { - System.out.println("Server started!"); + private static final Logger LOGGER = Logger.getLogger(Server.class.getName()); + + private final static String CHAT_SERVER_ADDRESS = "127.0.0.1"; + private final static int CHAT_SERVER_PORT = 23456; + + public static void main(String[] args) { + try { + final ServerSocket server = new ServerSocket(CHAT_SERVER_PORT, 50, InetAddress.getByName(CHAT_SERVER_ADDRESS)); + final Socket socket = server.accept(); + } catch (Exception e) { + LOGGER.log(Level.SEVERE, String.format("Cannot start server on %s:%d", CHAT_SERVER_ADDRESS, CHAT_SERVER_PORT)); + } } } \ No newline at end of file From c7a8fa46584af59fb79ca6e7497ee72e4f8b84e3 Mon Sep 17 00:00:00 2001 From: art Date: Fri, 12 Oct 2018 18:38:25 +0500 Subject: [PATCH 03/12] Add interaction between client and server --- src/chat/Client.java | 10 ++++++---- src/chat/Server.java | 14 +++++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/chat/Client.java b/src/chat/Client.java index 0c762d5..95fae6e 100644 --- a/src/chat/Client.java +++ b/src/chat/Client.java @@ -14,12 +14,14 @@ public class Client { private final static int CHAT_SERVER_PORT = 23456; public static void main(String[] args) { - try { - final Socket socket = new Socket(InetAddress.getByName(CHAT_SERVER_ADDRESS), CHAT_SERVER_PORT); - final DataInputStream input = new DataInputStream(socket.getInputStream()); + try (final Socket socket = new Socket(InetAddress.getByName(CHAT_SERVER_ADDRESS), CHAT_SERVER_PORT)) { final DataOutputStream output = new DataOutputStream(socket.getOutputStream()); + output.writeUTF("Hello from Client!"); + final DataInputStream input = new DataInputStream(socket.getInputStream()); + final String msg = input.readUTF(); + System.out.println(msg); } catch (Exception e) { - LOGGER.log(Level.SEVERE, String.format("Cannot connect to %s on port %d", CHAT_SERVER_ADDRESS, CHAT_SERVER_PORT)); + LOGGER.log(Level.SEVERE, String.format("Cannot interact with server on %s:%d", CHAT_SERVER_ADDRESS, CHAT_SERVER_PORT)); } } } \ No newline at end of file diff --git a/src/chat/Server.java b/src/chat/Server.java index 622c133..5e7f315 100644 --- a/src/chat/Server.java +++ b/src/chat/Server.java @@ -1,5 +1,7 @@ package chat; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; @@ -13,9 +15,15 @@ public class Server { private final static int CHAT_SERVER_PORT = 23456; public static void main(String[] args) { - try { - final ServerSocket server = new ServerSocket(CHAT_SERVER_PORT, 50, InetAddress.getByName(CHAT_SERVER_ADDRESS)); - final Socket socket = server.accept(); + try (final ServerSocket server = new ServerSocket(CHAT_SERVER_PORT, 50, InetAddress.getByName(CHAT_SERVER_ADDRESS)); + final Socket socket = server.accept()) { + + final DataInputStream input = new DataInputStream(socket.getInputStream()); + final String msg = input.readUTF(); + System.out.println(msg); + + final DataOutputStream output = new DataOutputStream(socket.getOutputStream()); + output.writeUTF("Hello from Server!"); } catch (Exception e) { LOGGER.log(Level.SEVERE, String.format("Cannot start server on %s:%d", CHAT_SERVER_ADDRESS, CHAT_SERVER_PORT)); } From 6bc66ed939c196f7cd8bb685f8cf33ced5c3b8d2 Mon Sep 17 00:00:00 2001 From: art Date: Fri, 12 Oct 2018 22:36:38 +0500 Subject: [PATCH 04/12] Accepting connection from multiple clients (thread per a client) --- src/chat/Client.java | 4 +- src/chat/ClientSocketHandler.java | 64 +++++++++++++++++++++++++++++++ src/chat/Configs.java | 9 +++++ src/chat/Server.java | 36 +++++++++-------- 4 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 src/chat/ClientSocketHandler.java create mode 100644 src/chat/Configs.java diff --git a/src/chat/Client.java b/src/chat/Client.java index 95fae6e..e9dc6ca 100644 --- a/src/chat/Client.java +++ b/src/chat/Client.java @@ -14,14 +14,14 @@ public class Client { private final static int CHAT_SERVER_PORT = 23456; public static void main(String[] args) { - try (final Socket socket = new Socket(InetAddress.getByName(CHAT_SERVER_ADDRESS), CHAT_SERVER_PORT)) { + try (final Socket socket = new Socket(InetAddress.getByName("localhost"), CHAT_SERVER_PORT)) { final DataOutputStream output = new DataOutputStream(socket.getOutputStream()); output.writeUTF("Hello from Client!"); final DataInputStream input = new DataInputStream(socket.getInputStream()); final String msg = input.readUTF(); System.out.println(msg); } catch (Exception e) { - LOGGER.log(Level.SEVERE, String.format("Cannot interact with server on %s:%d", CHAT_SERVER_ADDRESS, CHAT_SERVER_PORT)); + LOGGER.log(Level.SEVERE, String.format("Cannot interact with server on %s:%d", CHAT_SERVER_ADDRESS, CHAT_SERVER_PORT), e); } } } \ No newline at end of file diff --git a/src/chat/ClientSocketHandler.java b/src/chat/ClientSocketHandler.java new file mode 100644 index 0000000..68209f7 --- /dev/null +++ b/src/chat/ClientSocketHandler.java @@ -0,0 +1,64 @@ +package chat; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class ClientSocketHandler extends Thread { + private static final Logger LOGGER = Logger.getLogger(ClientSocketHandler.class.getName()); + + private final Socket clientSocket; + private final String clientName; + + private final DataInputStream input; + private final DataOutputStream output; + private int wordsCounter; + + public ClientSocketHandler(Socket client, String name) throws IOException { + this.clientSocket = client; + this.clientName = name; + this.input = new DataInputStream(client.getInputStream()); + this.output = new DataOutputStream(client.getOutputStream()); + } + + @Override + public void run() { + try { + Thread.sleep(2000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + while (true) { + try { + final String receivedMsg = input.readUTF(); + if (receivedMsg.trim().equalsIgnoreCase("exit")) { + disconnect(); + break; + } + + System.out.println(clientName + ":" + receivedMsg); + + final String[] words = receivedMsg.split("\\s+"); + wordsCounter += words.length; + + output.writeUTF(String.format("You sent %d words total", wordsCounter)); + } catch (IOException e) { + LOGGER.log(Level.SEVERE, String.format("Cannot interact with %s", clientName)); + } + } + } + + private void disconnect() { + try { + clientSocket.close(); + input.close(); + output.close(); + System.out.printf("%s disconnected\n", clientName); + } catch (IOException e) { + LOGGER.log(Level.SEVERE, String.format("Cannot disconnect %s", clientName)); + } + } +} diff --git a/src/chat/Configs.java b/src/chat/Configs.java new file mode 100644 index 0000000..6d7fcee --- /dev/null +++ b/src/chat/Configs.java @@ -0,0 +1,9 @@ +package chat; + +public final class Configs { + + private Configs() { } + + public static final int CHAR_SERVER_PORT = 23456; + public static final String CHAR_SERVER_ADDRESS = "127.0.0.1"; +} diff --git a/src/chat/Server.java b/src/chat/Server.java index 5e7f315..9be1f83 100644 --- a/src/chat/Server.java +++ b/src/chat/Server.java @@ -1,8 +1,6 @@ package chat; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.net.InetAddress; +import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.logging.Level; @@ -10,22 +8,28 @@ public class Server { private static final Logger LOGGER = Logger.getLogger(Server.class.getName()); - - private final static String CHAT_SERVER_ADDRESS = "127.0.0.1"; - private final static int CHAT_SERVER_PORT = 23456; + private static int clientNumber = 1; public static void main(String[] args) { - try (final ServerSocket server = new ServerSocket(CHAT_SERVER_PORT, 50, InetAddress.getByName(CHAT_SERVER_ADDRESS)); - final Socket socket = server.accept()) { - - final DataInputStream input = new DataInputStream(socket.getInputStream()); - final String msg = input.readUTF(); - System.out.println(msg); + try (final ServerSocket server = new ServerSocket(Configs.CHAR_SERVER_PORT)) { + LOGGER.info(String.format("The chat server has been started on port %d", server.getLocalPort())); + while (true) { + regNewClient(server); + } + } catch (IOException e) { + LOGGER.log(Level.SEVERE, String.format("Cannot start server on %d", Configs.CHAR_SERVER_PORT), e); + } + } - final DataOutputStream output = new DataOutputStream(socket.getOutputStream()); - output.writeUTF("Hello from Server!"); - } catch (Exception e) { - LOGGER.log(Level.SEVERE, String.format("Cannot start server on %s:%d", CHAT_SERVER_ADDRESS, CHAT_SERVER_PORT)); + private static void regNewClient(ServerSocket server) { + try { + final Socket client = server.accept(); + final String clientName = "client-" + (clientNumber++); + final Thread clientThread = new ClientSocketHandler(client, clientName); + clientThread.start(); + System.out.printf("%s connected\n", clientName); + } catch (IOException e) { + LOGGER.log(Level.SEVERE, "Cannot register a new client", e); } } } \ No newline at end of file From 7af506bb99baa311a9e1f1d855ad8d82257d0d84 Mon Sep 17 00:00:00 2001 From: art Date: Fri, 12 Oct 2018 22:53:54 +0500 Subject: [PATCH 05/12] Processing client's messages in an infinite loop --- src/chat/Client.java | 31 +++++++++++++++++++++++-------- src/chat/ClientSocketHandler.java | 4 ++-- src/chat/Configs.java | 4 ++-- src/chat/Server.java | 6 +++--- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/chat/Client.java b/src/chat/Client.java index e9dc6ca..c533137 100644 --- a/src/chat/Client.java +++ b/src/chat/Client.java @@ -2,26 +2,41 @@ import java.io.DataInputStream; import java.io.DataOutputStream; +import java.io.IOException; import java.net.InetAddress; import java.net.Socket; +import java.util.Scanner; import java.util.logging.Level; import java.util.logging.Logger; public class Client { private static final Logger LOGGER = Logger.getLogger(Client.class.getName()); - private final static String CHAT_SERVER_ADDRESS = "127.0.0.1"; - private final static int CHAT_SERVER_PORT = 23456; - public static void main(String[] args) { - try (final Socket socket = new Socket(InetAddress.getByName("localhost"), CHAT_SERVER_PORT)) { + final Scanner scanner = new Scanner(System.in); + + try (final Socket socket = new Socket(InetAddress.getByName(Configs.CHAT_SERVER_ADDRESS), Configs.CHAT_SERVER_PORT)) { + LOGGER.info(String.format("Established connection to %s", socket.getRemoteSocketAddress().toString())); + final DataOutputStream output = new DataOutputStream(socket.getOutputStream()); - output.writeUTF("Hello from Client!"); final DataInputStream input = new DataInputStream(socket.getInputStream()); - final String msg = input.readUTF(); - System.out.println(msg); + + while (true) { + final String msgToSend = scanner.nextLine(); + output.writeUTF(msgToSend); + + if (msgToSend.trim().equalsIgnoreCase("exit")) { + socket.close(); + input.close(); + output.close(); + break; + } + + final String receivedMsg = input.readUTF(); + System.out.println(receivedMsg); + } } catch (Exception e) { - LOGGER.log(Level.SEVERE, String.format("Cannot interact with server on %s:%d", CHAT_SERVER_ADDRESS, CHAT_SERVER_PORT), e); + LOGGER.log(Level.SEVERE, "Cannot interact with the server", e); } } } \ No newline at end of file diff --git a/src/chat/ClientSocketHandler.java b/src/chat/ClientSocketHandler.java index 68209f7..bed04e3 100644 --- a/src/chat/ClientSocketHandler.java +++ b/src/chat/ClientSocketHandler.java @@ -39,7 +39,7 @@ public void run() { break; } - System.out.println(clientName + ":" + receivedMsg); + System.out.println(clientName + ": " + receivedMsg); final String[] words = receivedMsg.split("\\s+"); wordsCounter += words.length; @@ -56,7 +56,7 @@ private void disconnect() { clientSocket.close(); input.close(); output.close(); - System.out.printf("%s disconnected\n", clientName); + System.out.printf("%s disconnected from the server\n", clientName); } catch (IOException e) { LOGGER.log(Level.SEVERE, String.format("Cannot disconnect %s", clientName)); } diff --git a/src/chat/Configs.java b/src/chat/Configs.java index 6d7fcee..aaa5366 100644 --- a/src/chat/Configs.java +++ b/src/chat/Configs.java @@ -4,6 +4,6 @@ public final class Configs { private Configs() { } - public static final int CHAR_SERVER_PORT = 23456; - public static final String CHAR_SERVER_ADDRESS = "127.0.0.1"; + public static final int CHAT_SERVER_PORT = 23456; + public static final String CHAT_SERVER_ADDRESS = "127.0.0.1"; } diff --git a/src/chat/Server.java b/src/chat/Server.java index 9be1f83..36de63f 100644 --- a/src/chat/Server.java +++ b/src/chat/Server.java @@ -11,13 +11,13 @@ public class Server { private static int clientNumber = 1; public static void main(String[] args) { - try (final ServerSocket server = new ServerSocket(Configs.CHAR_SERVER_PORT)) { + try (final ServerSocket server = new ServerSocket(Configs.CHAT_SERVER_PORT)) { LOGGER.info(String.format("The chat server has been started on port %d", server.getLocalPort())); while (true) { regNewClient(server); } } catch (IOException e) { - LOGGER.log(Level.SEVERE, String.format("Cannot start server on %d", Configs.CHAR_SERVER_PORT), e); + LOGGER.log(Level.SEVERE, String.format("Cannot start server on %d", Configs.CHAT_SERVER_PORT), e); } } @@ -27,7 +27,7 @@ private static void regNewClient(ServerSocket server) { final String clientName = "client-" + (clientNumber++); final Thread clientThread = new ClientSocketHandler(client, clientName); clientThread.start(); - System.out.printf("%s connected\n", clientName); + System.out.printf("%s connected to the server\n", clientName); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Cannot register a new client", e); } From 8437810f1a05fe5daaf8a49a5a2feb4eee2df471 Mon Sep 17 00:00:00 2001 From: art Date: Fri, 12 Oct 2018 22:58:15 +0500 Subject: [PATCH 06/12] Perform small refactor --- src/chat/{ => clientside}/Client.java | 5 +++-- src/chat/{ => common}/Configs.java | 2 +- src/chat/{ => serverside}/ClientSocketHandler.java | 11 ++++++----- src/chat/{ => serverside}/Server.java | 4 +++- 4 files changed, 13 insertions(+), 9 deletions(-) rename src/chat/{ => clientside}/Client.java (96%) rename src/chat/{ => common}/Configs.java (89%) rename src/chat/{ => serverside}/ClientSocketHandler.java (89%) rename src/chat/{ => serverside}/Server.java (95%) diff --git a/src/chat/Client.java b/src/chat/clientside/Client.java similarity index 96% rename from src/chat/Client.java rename to src/chat/clientside/Client.java index c533137..bfb1e23 100644 --- a/src/chat/Client.java +++ b/src/chat/clientside/Client.java @@ -1,8 +1,9 @@ -package chat; +package chat.clientside; + +import chat.common.Configs; import java.io.DataInputStream; import java.io.DataOutputStream; -import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.util.Scanner; diff --git a/src/chat/Configs.java b/src/chat/common/Configs.java similarity index 89% rename from src/chat/Configs.java rename to src/chat/common/Configs.java index aaa5366..5656e6a 100644 --- a/src/chat/Configs.java +++ b/src/chat/common/Configs.java @@ -1,4 +1,4 @@ -package chat; +package chat.common; public final class Configs { diff --git a/src/chat/ClientSocketHandler.java b/src/chat/serverside/ClientSocketHandler.java similarity index 89% rename from src/chat/ClientSocketHandler.java rename to src/chat/serverside/ClientSocketHandler.java index bed04e3..8cc9372 100644 --- a/src/chat/ClientSocketHandler.java +++ b/src/chat/serverside/ClientSocketHandler.java @@ -1,4 +1,4 @@ -package chat; +package chat.serverside; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -31,8 +31,8 @@ public void run() { } catch (InterruptedException e) { e.printStackTrace(); } - while (true) { - try { + try { + while (true) { final String receivedMsg = input.readUTF(); if (receivedMsg.trim().equalsIgnoreCase("exit")) { disconnect(); @@ -45,9 +45,10 @@ public void run() { wordsCounter += words.length; output.writeUTF(String.format("You sent %d words total", wordsCounter)); - } catch (IOException e) { - LOGGER.log(Level.SEVERE, String.format("Cannot interact with %s", clientName)); } + } catch(IOException e){ + LOGGER.log(Level.SEVERE, String.format("Cannot interact with %s", clientName)); + disconnect(); } } diff --git a/src/chat/Server.java b/src/chat/serverside/Server.java similarity index 95% rename from src/chat/Server.java rename to src/chat/serverside/Server.java index 36de63f..d1846ef 100644 --- a/src/chat/Server.java +++ b/src/chat/serverside/Server.java @@ -1,4 +1,6 @@ -package chat; +package chat.serverside; + +import chat.common.Configs; import java.io.IOException; import java.net.ServerSocket; From fc4147a5b907a90df1dbee104b969a527bba87d5 Mon Sep 17 00:00:00 2001 From: artyom-b <43481254+artyom-b@users.noreply.github.com> Date: Fri, 12 Oct 2018 23:23:40 +0500 Subject: [PATCH 07/12] Remove temporary code --- src/chat/serverside/ClientSocketHandler.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/chat/serverside/ClientSocketHandler.java b/src/chat/serverside/ClientSocketHandler.java index 8cc9372..81fd6cc 100644 --- a/src/chat/serverside/ClientSocketHandler.java +++ b/src/chat/serverside/ClientSocketHandler.java @@ -26,11 +26,6 @@ public ClientSocketHandler(Socket client, String name) throws IOException { @Override public void run() { - try { - Thread.sleep(2000L); - } catch (InterruptedException e) { - e.printStackTrace(); - } try { while (true) { final String receivedMsg = input.readUTF(); From 138f6e11e2198df17e9265f938719503d1720bb2 Mon Sep 17 00:00:00 2001 From: art Date: Sat, 13 Oct 2018 02:14:53 +0500 Subject: [PATCH 08/12] Make group chat with named users --- src/chat/clientside/Client.java | 46 +++++++++++++++---- ...tSocketHandler.java => ClientHandler.java} | 41 +++++++++++------ src/chat/serverside/Server.java | 41 +++++++++++++---- 3 files changed, 96 insertions(+), 32 deletions(-) rename src/chat/serverside/{ClientSocketHandler.java => ClientHandler.java} (57%) diff --git a/src/chat/clientside/Client.java b/src/chat/clientside/Client.java index bfb1e23..9ba00f8 100644 --- a/src/chat/clientside/Client.java +++ b/src/chat/clientside/Client.java @@ -4,6 +4,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; +import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.util.Scanner; @@ -13,7 +14,13 @@ public class Client { private static final Logger LOGGER = Logger.getLogger(Client.class.getName()); - public static void main(String[] args) { + private final String name; + + public Client(String name) { + this.name = name; + } + + public void start() { final Scanner scanner = new Scanner(System.in); try (final Socket socket = new Socket(InetAddress.getByName(Configs.CHAT_SERVER_ADDRESS), Configs.CHAT_SERVER_PORT)) { @@ -22,22 +29,45 @@ public static void main(String[] args) { final DataOutputStream output = new DataOutputStream(socket.getOutputStream()); final DataInputStream input = new DataInputStream(socket.getInputStream()); + final Thread receivedMessagesHandler = new Thread(() -> { + try { + while (true) { + final String msg = input.readUTF(); + System.out.println(msg); + } + } catch(IOException e){ + LOGGER.log(Level.SEVERE, "Cannot interact with the server"); + } + }); + + receivedMessagesHandler.start(); + + output.writeUTF(name); + while (true) { final String msgToSend = scanner.nextLine(); output.writeUTF(msgToSend); - if (msgToSend.trim().equalsIgnoreCase("exit")) { - socket.close(); - input.close(); - output.close(); + if (msgToSend.trim().equalsIgnoreCase("/exit")) { break; } - - final String receivedMsg = input.readUTF(); - System.out.println(receivedMsg); } + + socket.close(); + input.close(); + output.close(); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Cannot interact with the server", e); } } + + public static void main(String[] args) { + if (args.length < 1) { + System.out.println("Please, specify your name as an argument when starting it."); + return; + } + + Client client = new Client(args[0]); + client.start(); + } } \ No newline at end of file diff --git a/src/chat/serverside/ClientSocketHandler.java b/src/chat/serverside/ClientHandler.java similarity index 57% rename from src/chat/serverside/ClientSocketHandler.java rename to src/chat/serverside/ClientHandler.java index 81fd6cc..c542130 100644 --- a/src/chat/serverside/ClientSocketHandler.java +++ b/src/chat/serverside/ClientHandler.java @@ -7,42 +7,49 @@ import java.util.logging.Level; import java.util.logging.Logger; -public class ClientSocketHandler extends Thread { - private static final Logger LOGGER = Logger.getLogger(ClientSocketHandler.class.getName()); +public class ClientHandler extends Thread { + private static final Logger LOGGER = Logger.getLogger(ClientHandler.class.getName()); + private final Server server; private final Socket clientSocket; - private final String clientName; private final DataInputStream input; private final DataOutputStream output; - private int wordsCounter; - public ClientSocketHandler(Socket client, String name) throws IOException { + private String clientName = "Unknown"; + + public ClientHandler(Server server, Socket client) throws IOException { + this.server = server; this.clientSocket = client; - this.clientName = name; this.input = new DataInputStream(client.getInputStream()); this.output = new DataOutputStream(client.getOutputStream()); } + public void sendMsg(String msg) throws IOException { + output.writeUTF(msg); + } + @Override public void run() { try { + this.clientName = input.readUTF(); + + final String helloMsg = String.format("%s is ready to start chatting\n", clientName); + server.broadcastMessage(helloMsg); + while (true) { - final String receivedMsg = input.readUTF(); - if (receivedMsg.trim().equalsIgnoreCase("exit")) { + final String msg = input.readUTF(); + if (msg.trim().equalsIgnoreCase("/exit")) { disconnect(); break; } - System.out.println(clientName + ": " + receivedMsg); - - final String[] words = receivedMsg.split("\\s+"); - wordsCounter += words.length; + LOGGER.info(String.format("%s sent \'%s\'", clientName, msg)); - output.writeUTF(String.format("You sent %d words total", wordsCounter)); + server.broadcastMessage(clientName + ": " + msg); } } catch(IOException e){ - LOGGER.log(Level.SEVERE, String.format("Cannot interact with %s", clientName)); + LOGGER.log(Level.SEVERE, String.format("Cannot interact with %s", clientName), e); disconnect(); } } @@ -54,7 +61,11 @@ private void disconnect() { output.close(); System.out.printf("%s disconnected from the server\n", clientName); } catch (IOException e) { - LOGGER.log(Level.SEVERE, String.format("Cannot disconnect %s", clientName)); + LOGGER.log(Level.SEVERE, String.format("Cannot disconnect %s", clientName), e); } } + + public String getClientName() { + return clientName; + } } diff --git a/src/chat/serverside/Server.java b/src/chat/serverside/Server.java index d1846ef..98f2c06 100644 --- a/src/chat/serverside/Server.java +++ b/src/chat/serverside/Server.java @@ -5,33 +5,56 @@ import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; +import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; public class Server { private static final Logger LOGGER = Logger.getLogger(Server.class.getName()); - private static int clientNumber = 1; - public static void main(String[] args) { - try (final ServerSocket server = new ServerSocket(Configs.CHAT_SERVER_PORT)) { + private static ArrayList handlers = new ArrayList<>(); + + private final int port; + + public Server(int port) { + this.port = port; + } + + public void start() { + try (final ServerSocket server = new ServerSocket(port)) { LOGGER.info(String.format("The chat server has been started on port %d", server.getLocalPort())); while (true) { - regNewClient(server); + LOGGER.info("Waiting for a client"); + final Socket client = server.accept(); + regNewClient(client); } } catch (IOException e) { LOGGER.log(Level.SEVERE, String.format("Cannot start server on %d", Configs.CHAT_SERVER_PORT), e); } } - private static void regNewClient(ServerSocket server) { + public synchronized void regNewClient(Socket client) { try { - final Socket client = server.accept(); - final String clientName = "client-" + (clientNumber++); - final Thread clientThread = new ClientSocketHandler(client, clientName); + final ClientHandler clientThread = new ClientHandler(this, client); clientThread.start(); - System.out.printf("%s connected to the server\n", clientName); + handlers.add(clientThread); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Cannot register a new client", e); } } + + public synchronized void broadcastMessage(String msg) { + handlers.forEach(handler -> { + try { + handler.sendMsg(msg); + } catch (IOException e) { + LOGGER.log(Level.SEVERE, String.format("Cannot send message to %s", handler.getClientName()), e); + } + }); + } + + public static void main(String[] args) { + final Server chatServer = new Server(Configs.CHAT_SERVER_PORT); + chatServer.start(); + } } \ No newline at end of file From ea79bc1230fcf850216176da8ff38027b6d00442 Mon Sep 17 00:00:00 2001 From: art Date: Sat, 13 Oct 2018 02:37:39 +0500 Subject: [PATCH 09/12] Display msg date --- src/chat/clientside/Client.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/chat/clientside/Client.java b/src/chat/clientside/Client.java index 9ba00f8..7f920da 100644 --- a/src/chat/clientside/Client.java +++ b/src/chat/clientside/Client.java @@ -7,6 +7,7 @@ import java.io.IOException; import java.net.InetAddress; import java.net.Socket; +import java.time.LocalDateTime; import java.util.Scanner; import java.util.logging.Level; import java.util.logging.Logger; @@ -33,7 +34,8 @@ public void start() { try { while (true) { final String msg = input.readUTF(); - System.out.println(msg); + final LocalDateTime now = LocalDateTime.now().withNano(0); + System.out.println(String.format("[%s] %s", now.toString(), msg)); } } catch(IOException e){ LOGGER.log(Level.SEVERE, "Cannot interact with the server"); From 9be1429f5bc42368d1abcbea0a6d3b9ec5386d10 Mon Sep 17 00:00:00 2001 From: art Date: Sat, 13 Oct 2018 02:40:25 +0500 Subject: [PATCH 10/12] Remove 'T' in date-time of messages --- src/chat/clientside/Client.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chat/clientside/Client.java b/src/chat/clientside/Client.java index 7f920da..b388545 100644 --- a/src/chat/clientside/Client.java +++ b/src/chat/clientside/Client.java @@ -35,7 +35,7 @@ public void start() { while (true) { final String msg = input.readUTF(); final LocalDateTime now = LocalDateTime.now().withNano(0); - System.out.println(String.format("[%s] %s", now.toString(), msg)); + System.out.println(String.format("[%s] %s", now.toString().replace('T', ' '), msg)); } } catch(IOException e){ LOGGER.log(Level.SEVERE, "Cannot interact with the server"); From f041805ac0f153be08028ad3f5c6662c802f056b Mon Sep 17 00:00:00 2001 From: art Date: Sat, 13 Oct 2018 10:03:24 +0500 Subject: [PATCH 11/12] Minor fixes --- src/chat/clientside/Client.java | 3 ++- src/chat/common/Commands.java | 16 ++++++++++++++++ src/chat/common/Configs.java | 1 + src/chat/serverside/ClientHandler.java | 26 ++++++++++++++++++++------ src/chat/serverside/Server.java | 10 +++++++++- 5 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 src/chat/common/Commands.java diff --git a/src/chat/clientside/Client.java b/src/chat/clientside/Client.java index b388545..ea03ae7 100644 --- a/src/chat/clientside/Client.java +++ b/src/chat/clientside/Client.java @@ -1,5 +1,6 @@ package chat.clientside; +import chat.common.Commands; import chat.common.Configs; import java.io.DataInputStream; @@ -50,7 +51,7 @@ public void start() { final String msgToSend = scanner.nextLine(); output.writeUTF(msgToSend); - if (msgToSend.trim().equalsIgnoreCase("/exit")) { + if (msgToSend.trim().equalsIgnoreCase(Commands.EXIT.getCode())) { break; } } diff --git a/src/chat/common/Commands.java b/src/chat/common/Commands.java new file mode 100644 index 0000000..a940ed6 --- /dev/null +++ b/src/chat/common/Commands.java @@ -0,0 +1,16 @@ +package chat.common; + +public enum Commands { + + EXIT("/exit"), LIST("/list"); + + Commands(String code) { + this.code = code; + } + + private final String code; + + public String getCode() { + return code; + } +} diff --git a/src/chat/common/Configs.java b/src/chat/common/Configs.java index 5656e6a..02930ff 100644 --- a/src/chat/common/Configs.java +++ b/src/chat/common/Configs.java @@ -6,4 +6,5 @@ private Configs() { } public static final int CHAT_SERVER_PORT = 23456; public static final String CHAT_SERVER_ADDRESS = "127.0.0.1"; + public static final int THREAD_POOL_SIZE = 1; } diff --git a/src/chat/serverside/ClientHandler.java b/src/chat/serverside/ClientHandler.java index c542130..bf677ca 100644 --- a/src/chat/serverside/ClientHandler.java +++ b/src/chat/serverside/ClientHandler.java @@ -1,9 +1,12 @@ package chat.serverside; +import chat.common.Commands; + import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; +import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; @@ -16,9 +19,11 @@ public class ClientHandler extends Thread { private final DataInputStream input; private final DataOutputStream output; + private final UUID clientId; private String clientName = "Unknown"; - public ClientHandler(Server server, Socket client) throws IOException { + public ClientHandler(UUID clientId, Server server, Socket client) throws IOException { + this.clientId = clientId; this.server = server; this.clientSocket = client; this.input = new DataInputStream(client.getInputStream()); @@ -38,15 +43,19 @@ public void run() { server.broadcastMessage(helloMsg); while (true) { + if (clientSocket.isClosed()) { + break; + } + final String msg = input.readUTF(); - if (msg.trim().equalsIgnoreCase("/exit")) { + if (msg.trim().equalsIgnoreCase(Commands.EXIT.getCode())) { disconnect(); break; } - LOGGER.info(String.format("%s sent \'%s\'", clientName, msg)); - - server.broadcastMessage(clientName + ": " + msg); + final String msgWithClient = clientName + ": " + msg; + LOGGER.info(msgWithClient); + server.broadcastMessage(msgWithClient); } } catch(IOException e){ LOGGER.log(Level.SEVERE, String.format("Cannot interact with %s", clientName), e); @@ -59,13 +68,18 @@ private void disconnect() { clientSocket.close(); input.close(); output.close(); - System.out.printf("%s disconnected from the server\n", clientName); } catch (IOException e) { LOGGER.log(Level.SEVERE, String.format("Cannot disconnect %s", clientName), e); } + server.dropClient(clientId); + server.broadcastMessage(String.format("%s disconnected from the server\n", clientName)); } public String getClientName() { return clientName; } + + public UUID getClientId() { + return clientId; + } } diff --git a/src/chat/serverside/Server.java b/src/chat/serverside/Server.java index 98f2c06..1e49dd0 100644 --- a/src/chat/serverside/Server.java +++ b/src/chat/serverside/Server.java @@ -6,6 +6,10 @@ import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.logging.Level; import java.util.logging.Logger; @@ -35,7 +39,7 @@ public void start() { public synchronized void regNewClient(Socket client) { try { - final ClientHandler clientThread = new ClientHandler(this, client); + final ClientHandler clientThread = new ClientHandler(UUID.randomUUID(), this, client); clientThread.start(); handlers.add(clientThread); } catch (IOException e) { @@ -43,6 +47,10 @@ public synchronized void regNewClient(Socket client) { } } + public synchronized void dropClient(UUID clientId) { + handlers.removeIf(client -> Objects.equals(client.getClientId(), clientId)); + } + public synchronized void broadcastMessage(String msg) { handlers.forEach(handler -> { try { From ba0b02a77353b3f5c5e8336cc4811e9b2d89a54b Mon Sep 17 00:00:00 2001 From: art Date: Sat, 13 Oct 2018 10:18:14 +0500 Subject: [PATCH 12/12] Minor fixes 2 --- src/chat/serverside/ClientHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/chat/serverside/ClientHandler.java b/src/chat/serverside/ClientHandler.java index bf677ca..2c3f12c 100644 --- a/src/chat/serverside/ClientHandler.java +++ b/src/chat/serverside/ClientHandler.java @@ -32,6 +32,7 @@ public ClientHandler(UUID clientId, Server server, Socket client) throws IOExcep public void sendMsg(String msg) throws IOException { output.writeUTF(msg); + output.flush(); } @Override