From 4340438248c62c9c1c0f24848beff9c5b32aa07d Mon Sep 17 00:00:00 2001 From: emi <87698845+emikode@users.noreply.github.com> Date: Tue, 28 Feb 2023 09:49:51 +0100 Subject: [PATCH 1/3] Added ".java" files. Added source code. --- ClientCalculator.java | 39 ++++++++++++ ServerCalculator.java | 140 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 ClientCalculator.java create mode 100644 ServerCalculator.java diff --git a/ClientCalculator.java b/ClientCalculator.java new file mode 100644 index 0000000..b4334f8 --- /dev/null +++ b/ClientCalculator.java @@ -0,0 +1,39 @@ +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.Socket; +import java.util.Scanner; + +public class ClientCalculator { + public static void main(String[] args) { + System.out.println("Connessione al server..."); + try(Socket connessioneServer = new Socket("localhost",5000)){ + String IPServer = connessioneServer.getRemoteSocketAddress().toString(); + String IPLocale = connessioneServer.getLocalAddress().toString(); + System.out.println("Connessione col server stabilita:\nIP Server remoto: " + IPServer + "\nIP Client: " + IPLocale); + + BufferedReader streamInput = new BufferedReader(new InputStreamReader(connessioneServer.getInputStream())); + PrintWriter invioDati = new PrintWriter(new OutputStreamWriter(connessioneServer.getOutputStream()),true); + + Scanner inputStreamReader = new Scanner(System.in); + + System.out.println("Inserisci l'espressione da calcolare: "); + String espressioneInput = inputStreamReader.nextLine(); + + System.out.println("Invio dell'espressione al server..."); + invioDati.println(espressioneInput); + + System.out.println("Attesa risposta server..."); + String rispostaServer = streamInput.readLine(); + + System.out.println("Risposta server ricevuta: " + rispostaServer); + + connessioneServer.close(); + inputStreamReader.close(); + }catch(Exception e){ + //Scrive sull'error stream (Visualizzazione in colore rosso nella shell di IntelliJ) + System.err.println("Errore durante la connessione al server: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/ServerCalculator.java b/ServerCalculator.java new file mode 100644 index 0000000..79c09eb --- /dev/null +++ b/ServerCalculator.java @@ -0,0 +1,140 @@ +import java.io.*; +import java.net.*; +import java.util.*; + +public class INGENITO_ServerCalcolatrice{ + static int portaDelServer = 5000; + + public static Stack reverseStack(Stack stack){ + Stack reversedStack = new Stack(); + + while(!stack.empty()){ + reversedStack.push(stack.pop()); + } + + return reversedStack; + } + + public static void elabora(Socket clientSocket){ + try{ + //InputStreamReader, utilizza una tecnica di lettura sequenziale, per cui legge dal client un byte alla volta. + //BufferedReader invece, utilizza una tecnica di "Buffering", + //per cui legge l'intera stringa in RAM (carattere per carattere, invece di leggere per bytes), + //velocizzando le future operazioni di lettura. + //BufferedReader non può leggere il buffer di input direttamente, quindi utilizziamo InputStreamReader + //come "interfaccia" per poi permettere a BufferedReader la lettura per caratteri. + BufferedReader inputStreamClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + + //PrintWriter permette di formattare i dati per la scrittura (partendo dai dati primitivi di Java),OutputStreamWriter è un wrapper della classe OutputStream che permette di scrivere stringhe e caratteri, al posto di bytes codificati. + PrintWriter outputStreamClient = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()),true); + + //ora, possiamo utilizzare queste due interfacce per le operazioni di I/O: + + System.out.println("In attesa del messaggio da parte del client..."); + String messaggioClient = inputStreamClient.readLine(); + + System.out.println("Messaggio ricevuto: " + messaggioClient); + + //Esempio possibile stringa ricevuta: 15*2-3+8/6-2 + + Double rispostaClient=0.0; + Stack numeri= new Stack(); + Stack operandi = new Stack(); + + char operando; + Double num; + + String[] parsedElements = messaggioClient.split("(?<=[-+*^/\\(\\)])|(?=[-+*^/\\(\\)])"); + + //Riempio i due stack "numeri" e "operandi", ed eseguo già divisioni e moltiplicazioni. + numeri.push(Double.parseDouble(parsedElements[0])); + + for(int i=1;i<=parsedElements.length-2;i+=2){ + try{ + operando = parsedElements[i].toCharArray()[0]; + num = Double.parseDouble(parsedElements[i+1]); + + if(operando=='*'){ + numeri.push(numeri.pop()*num); + }else if(operando=='/'){ + numeri.push(numeri.pop()/num); + }else if(operando=='^'){ + numeri.push(Math.pow(numeri.pop(),num)); + }else{ + numeri.push(num); + operandi.push(operando); + } + }catch(Exception e){ + System.out.println("Espressione formattata male."); + } + } + + numeri = reverseStack(numeri); + operandi = reverseStack(operandi); + + /*System.out.println("Contenuto stack numeri:"); + while(!numeri.empty()){ + System.out.println(numeri.pop()); + } + + System.out.println("Contenuto stack operandi:"); + while(!operandi.empty()){ + System.out.println(operandi.pop()); + }*/ + + //addizioni e sottrazioni + + rispostaClient = numeri.pop(); + + while(!numeri.empty() && !operandi.empty()){ + operando = operandi.pop(); + num = numeri.pop(); + if(operando == '+'){ + rispostaClient += num; + }else if(operando == '-'){ + rispostaClient -= num; + } + } + + System.out.println("Invio risposta al client..."); + outputStreamClient.println(rispostaClient); + + System.out.println("Risposta inviata con successo."); + + }catch(Exception e){ + System.err.println("Errore durante l'elaborazione dei dati: " + e.getMessage()); + } + + } + + public static void main(String args[]) { + + //implementazione "portable" del paradigma client-server, è inserito in un blocco + //try-catch, perchè genera un eccezione se il server non può esser reso + //risponibile sulla porta specificata (per un qualsiasi motivo). + try(ServerSocket serverSocket = new ServerSocket(portaDelServer)){ + System.out.println("Il Server è disponibile e in ascolto sulla porta: " + portaDelServer + " , IP:" + serverSocket.getLocalSocketAddress()); + + while(true){ + //accetta richieste in entrata, in un oggetto di tipo "Socket". + try(Socket clientSocket = serverSocket.accept()){ + String indirizzoIPclient = clientSocket.getRemoteSocketAddress().toString(); + //memorizza l'indirizzo IP del client a cui il server è connesso, restituisce NULL se la connessione non è andata a buon fine. + + System.out.println("Connesso con il client, IP: " + indirizzoIPclient); + + elabora(clientSocket); + + System.out.println("Chiusura connessione client."); + clientSocket.close(); + }catch (Exception e){ + System.err.println("Errore durante la connessione col client: " + e.getMessage()); + } + + } + + }catch(Exception e){ + System.err.println("Errore durante l'esecuzione del codice server" + e.getMessage()); + } + } +} \ No newline at end of file From a7340e564ce6e4e453055a1010d2697a36b281f9 Mon Sep 17 00:00:00 2001 From: emi <87698845+emikode@users.noreply.github.com> Date: Tue, 28 Feb 2023 10:00:12 +0100 Subject: [PATCH 2/3] Updated "README.md". --- README.md | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 225 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7faf5e6..7d58922 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,225 @@ -# ClientServer-Calculator-Java -Simple Client-Server calculator, written in Java. +# Java Client-Server Calculator: + +--- + +> Simple Client-Server calculator, written in Java using sockets. +> + +--- + +## Code: + +### Client: + +```java +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.Socket; +import java.util.Scanner; + +public class ClientCalculator { + public static void main(String[] args) { + System.out.println("Connessione al server..."); + try(Socket connessioneServer = new Socket("localhost",5000)){ + String IPServer = connessioneServer.getRemoteSocketAddress().toString(); + String IPLocale = connessioneServer.getLocalAddress().toString(); + System.out.println("Connessione col server stabilita:\nIP Server remoto: " + IPServer + "\nIP Client: " + IPLocale); + + BufferedReader streamInput = new BufferedReader(new InputStreamReader(connessioneServer.getInputStream())); + PrintWriter invioDati = new PrintWriter(new OutputStreamWriter(connessioneServer.getOutputStream()),true); + + Scanner inputStreamReader = new Scanner(System.in); + + System.out.println("Inserisci l'espressione da calcolare: "); + String espressioneInput = inputStreamReader.nextLine(); + + System.out.println("Invio dell'espressione al server..."); + invioDati.println(espressioneInput); + + System.out.println("Attesa risposta server..."); + String rispostaServer = streamInput.readLine(); + + System.out.println("Risposta server ricevuta: " + rispostaServer); + + connessioneServer.close(); + inputStreamReader.close(); + }catch(Exception e){ + //Scrive sull'error stream (Visualizzazione in colore rosso nella shell di IntelliJ) + System.err.println("Errore durante la connessione al server: " + e.getMessage()); + } + } +} +``` + +### Server: + +```java +import java.io.*; +import java.net.*; +import java.util.*; + +public class ServerCalcolatrice{ + static int portaDelServer = 5000; + + public static Stack reverseStack(Stack stack){ + Stack reversedStack = new Stack(); + + while(!stack.empty()){ + reversedStack.push(stack.pop()); + } + + return reversedStack; + } + + public static void elabora(Socket clientSocket){ + try{ + //InputStreamReader, utilizza una tecnica di lettura sequenziale, per cui legge dal client un byte alla volta. + //BufferedReader invece, utilizza una tecnica di "Buffering", + //per cui legge l'intera stringa in RAM (carattere per carattere, invece di leggere per bytes), + //velocizzando le future operazioni di lettura. + //BufferedReader non può leggere il buffer di input direttamente, quindi utilizziamo InputStreamReader + //come "interfaccia" per poi permettere a BufferedReader la lettura per caratteri. + BufferedReader inputStreamClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + + //PrintWriter permette di formattare i dati per la scrittura (partendo dai dati primitivi di Java),OutputStreamWriter è un wrapper della classe OutputStream che permette di scrivere stringhe e caratteri, al posto di bytes codificati. + PrintWriter outputStreamClient = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()),true); + + //ora, possiamo utilizzare queste due interfacce per le operazioni di I/O: + + System.out.println("In attesa del messaggio da parte del client..."); + String messaggioClient = inputStreamClient.readLine(); + + System.out.println("Messaggio ricevuto: " + messaggioClient); + + //Esempio possibile stringa ricevuta: 15*2-3+8/6-2 + + Double rispostaClient=0.0; + Stack numeri= new Stack(); + Stack operandi = new Stack(); + + char operando; + Double num; + + String[] parsedElements = messaggioClient.split("(?<=[-+*^/\\(\\)])|(?=[-+*^/\\(\\)])"); + + //Riempio i due stack "numeri" e "operandi", ed eseguo già divisioni e moltiplicazioni. + numeri.push(Double.parseDouble(parsedElements[0])); + + for(int i=1;i<=parsedElements.length-2;i+=2){ + try{ + operando = parsedElements[i].toCharArray()[0]; + num = Double.parseDouble(parsedElements[i+1]); + + if(operando=='*'){ + numeri.push(numeri.pop()*num); + }else if(operando=='/'){ + numeri.push(numeri.pop()/num); + }else if(operando=='^'){ + numeri.push(Math.pow(numeri.pop(),num)); + }else{ + numeri.push(num); + operandi.push(operando); + } + }catch(Exception e){ + System.out.println("Espressione formattata male."); + } + } + + numeri = reverseStack(numeri); + operandi = reverseStack(operandi); + + /*System.out.println("Contenuto stack numeri:"); + while(!numeri.empty()){ + System.out.println(numeri.pop()); + } + + System.out.println("Contenuto stack operandi:"); + while(!operandi.empty()){ + System.out.println(operandi.pop()); + }*/ + + //addizioni e sottrazioni + + rispostaClient = numeri.pop(); + + while(!numeri.empty() && !operandi.empty()){ + operando = operandi.pop(); + num = numeri.pop(); + if(operando == '+'){ + rispostaClient += num; + }else if(operando == '-'){ + rispostaClient -= num; + } + } + + System.out.println("Invio risposta al client..."); + outputStreamClient.println(rispostaClient); + + System.out.println("Risposta inviata con successo."); + + }catch(Exception e){ + System.err.println("Errore durante l'elaborazione dei dati: " + e.getMessage()); + } + + } + + public static void main(String args[]) { + + //implementazione "portable" del paradigma client-server, è inserito in un blocco + //try-catch, perchè genera un eccezione se il server non può esser reso + //risponibile sulla porta specificata (per un qualsiasi motivo). + try(ServerSocket serverSocket = new ServerSocket(portaDelServer)){ + System.out.println("Il Server è disponibile e in ascolto sulla porta: " + portaDelServer + " , IP:" + serverSocket.getLocalSocketAddress()); + + while(true){ + //accetta richieste in entrata, in un oggetto di tipo "Socket". + try(Socket clientSocket = serverSocket.accept()){ + String indirizzoIPclient = clientSocket.getRemoteSocketAddress().toString(); + //memorizza l'indirizzo IP del client a cui il server è connesso, restituisce NULL se la connessione non è andata a buon fine. + + System.out.println("Connesso con il client, IP: " + indirizzoIPclient); + + elabora(clientSocket); + + System.out.println("Chiusura connessione client."); + clientSocket.close(); + }catch (Exception e){ + System.err.println("Errore durante la connessione col client: " + e.getMessage()); + } + + } + + }catch(Exception e){ + System.err.println("Errore durante l'esecuzione del codice server" + e.getMessage()); + } + } +} +``` + +--- + +## Technologies Used + +- **Java** + +--- + +## Usage + +Execute the **server** code **first**, than you can execute the **client** code. + +Write your math expression as **strings**, in **infix-notation**. + +The server will automatically **parse** the expression, and calculate the result. + +Supports **[* / + - % ^]** operands (**multiply**, **divide**, **add**, **subtract**, **modulus**, **pow**). + +--- + +## Contact + +Coded by **@emikode** - feel free to contact me! + +--- From b742aa14ee8b7ac1da19d17829a76dab99698f53 Mon Sep 17 00:00:00 2001 From: emi <87698845+emikodes@users.noreply.github.com> Date: Mon, 6 Mar 2023 12:16:48 +0100 Subject: [PATCH 3/3] Changed username --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d58922..1414f27 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,6 @@ Supports **[* / + - % ^]** operands (**multiply**, **divide**, **add**, **subtra ## Contact -Coded by **@emikode** - feel free to contact me! +Coded by **@emikodes** - feel free to contact me! ---