Visualizzazione dei risultati da 1 a 7 su 7

Discussione: Server - Client

  1. #1

    Server - Client

    Ciao a tutti ragazzi. Spero mi riusciate ad aiutare, sto impazzendo da giorni!

    Devo fare un applicazione client server un po' complessa ma ho un grosso problema.
    Ho realizzato un piccolo client che fa domande ad un server che prontamente risponde.
    Il problema sta nel fatto che sono riuscito a far comunicare le due applicazioni una riga per volta.
    cioè il client invia una richiesta su una riga e il server risponde su una riga.
    Io vorrei, però che il server rispondesse su più righe.
    Esempio
    situazione odierna

    Client:
    Come ti chiami?
    Server:
    Mi chiamo server 123

    Quello che vorrei

    Client
    come ti chiami?
    Server
    Mi chiamo 123
    Ti piace il mio nome?

    L'ho fatta veramente spicciola...
    posto il codice del client e server come lo realizzato io...
    Mi sa che dovrei lavorare sui byte ma non riesco a capire proprio
    Aspetto voi

    Client

    codice:
    import java.net.*;
    import java.io.*;
    
    public class Client {
        public static void main(String[] args) throws IOException {
    
            Socket Socket = null;
            PrintWriter out = null;
            BufferedReader in = null;
    
            try {
                Socket = new Socket("localhost", 4444);
                out = new PrintWriter(Socket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(Socket.getInputStream()));
            } catch (UnknownHostException e) {
                System.err.println("Non conoscol'host.");
                System.exit(1);
            } catch (IOException e) {
                System.err.println("Errore");
                System.exit(1);
            }
    
            BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
            String fromServer;
            String fromUser;
    
            while ((fromServer = in.readLine()) != null) {
                System.out.println("Server: " + fromServer);
                if (fromServer.equals("Bye."))
                    break;
    		    
                fromUser = stdIn.readLine();
    	    if (fromUser != null) {
                    System.out.println("Client: " + fromUser);
                    out.println(fromUser);
    	    }
            }
    
            out.close();
            in.close();
            stdIn.close();
            Socket.close();
        }
    }

    Server

    codice:
    import java.net.*;
    import java.io.*;
    
    public class Server {
        public static void main(String[] args) throws IOException {
    
            ServerSocket serverSocket = null;
            try {
                serverSocket = new ServerSocket(4444);
            } catch (IOException e) {
                System.err.println("Porta occupata");
                System.exit(1);
            }
    
            Socket clientSocket = null;
            try {
                clientSocket = serverSocket.accept();
            } catch (IOException e) {
                System.err.println("Non accettato.");
                System.exit(1);
            }
    
            PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
    				new InputStreamReader(
    				clientSocket.getInputStream()));
            String inputLine, outputLine;
            
            outputLine = "Server avviato!!! e Sei connesso";
            out.println(outputLine);
    
            while ((inputLine = in.readLine()) != null) {
            	if (inputLine.equals("PROVA"))
            		outputLine="prova andata a buon fine";
            	else if (inputLine.equals("OK"))
            		outputLine="ok ok";
            	else if (inputLine.equals("fine"))
            		outputLine="Bye.";
            	
            	out.println(outputLine);
                 if (outputLine.equals("Bye."))
                    break;
            }
            out.close();
            in.close();
            clientSocket.close();
            serverSocket.close();
        }
    }

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: Server - Client

    Originariamente inviato da ilblondobari86
    Io vorrei, però che il server rispondesse su più righe.
    Benissimo ... ma devi stabilire innanzitutto se il numero di righe in risposta è fisso o variabile. Se è fisso, lo sa il server e lo deve sapere implicitamente anche il client (il client si aspetta sempre X righe). Se è variabile allora devi stabilire tu il modo con cui il server fa sapere al client che non ci sono più righe. Il server potrebbe indicare a priori il numero di righe oppure inviare una riga finale di "marker" per indicare la fine della risposta.

    Originariamente inviato da ilblondobari86
    Mi sa che dovrei lavorare sui byte
    No, se il protocollo che ti stai "inventando" tu è fatto "a righe" .... allora continua a righe!

    E a proposito di byte, c'è una questione a cui nessuno fa mai caso in queste situazioni, ovvero il charset/encoding usato per (de)codificare i byte sugli stream. Hai usato i costruttori PrintWriter(OutputStream, boolean) e InputStreamReader(InputStream). Entrambi usano implicitamente (tu infatti non hai esplicitato alcunché a riguardo) il charset di "default" della piattaforma. Finché client e server sono la stessa macchina fisica o due macchine distinte con lo stesso S.O. configurato uguale .... ti va bene. Se i charset di default di client e server sono diversi .... non so che caratteri ti ritrovi ....
    Quando si trasferiscono "caratteri" su socket e a maggior ragione in un protocollo interamente a caratteri fatto "a righe", è ottima cosa stabilire a priori un charset ben preciso, ad esempio UTF-8.


    Infine, giusto per tua conoscenza, la gestione delle eccezioni l'hai fatta molto blanda e comunque inappropriata. E il server non l'hai fatto né "sequenziale" (detto anche "iterativo") né "concorrente", serve 1 solo client e poi termina .... quindi poco utile.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Innanzitutto ti ringrazio per la risposta molto chiara ed esaustiva.
    Premetto che le due classi che ho riportato qui sono un esempio minimo di ciò che dovrei fare.
    Nel mio progetto il server ha una programmazione multithread con la gestione di più client per volta e il protocollo l'ho definito in un altra classe.
    Qui ho riportato un esempio di ciò che mi serviva.
    Il problema è che anche il server multithead che ho fatto ha il problema di trasmettere una riga per volta.

    E a proposito di byte, c'è una questione a cui nessuno fa mai caso in queste situazioni, ovvero il charset/encoding usato per (de)codificare i byte sugli stream. Hai usato i costruttori PrintWriter(OutputStream, boolean) e InputStreamReader(InputStream). Entrambi usano implicitamente (tu infatti non hai esplicitato alcunché a riguardo) il charset di "default" della piattaforma.
    Per quanto riguarda l'inputStreamReader nel costruttore aggiungo il charset di caratteri.
    Ma per quanto riguarda il printwriter? dove lo posso definire il charset?
    Questi sono i costruttori che io conosco
    codice:
    PrintWriter(OutputStream out)
    PrintWriter(OutputStream out, boolean autoFlush)
    PrintWriter(Writer out)
    PrintWriter(Writer out, boolean autoFlush)
    Per quanto riguarda la comunicazione del server voglio che il numero di righe in risposta sia variabile.
    Quindi devo agire per forza indicando il numero di righe da trasmettere o inviando un marker?Cioè non posso controllare sul client quando finisce lo stream del server?
    Ho provato a fare una chiamata con il telnet al mio server e questo riesce a ricevere anche più righe per volta senza che il mio server indichi quando ha finito di "parlare". Come fa?
    O un server http, ad esempio, che risponde con un'intera pagina http e non con una sola riga come funziona?
    Infine, giusto per tua conoscenza, la gestione delle eccezioni l'hai fatta molto blanda e comunque inappropriata
    Veramente? Come l'avrei dovuta fare per esempio?

    Avrei, inoltre, un altro problema...
    Nel mio progetto c'è una classe server che ascolta sulla porta num e ogni qualvolta si connette un client chiama un thread che gestisce la comunicazione con il client.
    Il thread server poi chiama un altro thread nel caso in cui gli venga chiesto di fare un'altra operazione particolare (che nel caso in particolare è uno scanner di una pagina). Ora, questo sotto thread come fa a spedire la risposta al giusto client?
    Ho pensato di inserire ogni socket del client in un vettore. Poi, però, non so nel sotto thread, quando devo dare la risposta a prendere la socket che l'ha invocato...
    Non so se sono stato chiaro. Se avete bisogno posto il codice.

    Comunque grazie....
    Sto progetto mi sta facendo impazzire.

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da ilblondobari86
    Innanzitutto ti ringrazio per la risposta molto chiara ed esaustiva.
    Premetto che le due classi che ho riportato qui sono un esempio minimo di ciò che dovrei fare.
    Nel mio progetto il server ha una programmazione multithread con la gestione di più client per volta e il protocollo l'ho definito in un altra classe.
    Qui ho riportato un esempio di ciò che mi serviva.
    Ok, bene.

    Originariamente inviato da ilblondobari86
    Per quanto riguarda l'inputStreamReader nel costruttore aggiungo il charset di caratteri.
    Ma per quanto riguarda il printwriter? dove lo posso definire il charset?
    Questi sono i costruttori che io conosco
    codice:
    PrintWriter(OutputStream out)
    PrintWriter(OutputStream out, boolean autoFlush)
    PrintWriter(Writer out)
    PrintWriter(Writer out, boolean autoFlush)
    Se guardi nella documentazione di PrintWriter troverai che ci sono dei costruttori che hanno un parametro String csn (il nome del charset) ma ..... purtroppo 1) ricevono un nome di "file" (String/File) e 2) sono disponibili solo da Java 5. Quindi non sono questi di interesse per questo tuo caso.

    Però come ben già sai c'è quello che riceve un Writer. Ed esiste OutputStreamWriter, che è il "simmetrico" di InputStreamReader!!

    Originariamente inviato da ilblondobari86
    Per quanto riguarda la comunicazione del server voglio che il numero di righe in risposta sia variabile.
    Quindi devo agire per forza indicando il numero di righe da trasmettere o inviando un marker?Cioè non posso controllare sul client quando finisce lo stream del server?
    Se fai il classico ciclo while per leggere continuamente righe .... non finisce mai .... finirebbe solo se si chiude lo stream (e non è quello che ti interessa visto che la tua comunicazione consiste in più domande/risposte).
    Quindi un readLine() sarebbe sempre "in attesa".
    Pertanto devi trovare un modo per far sì che il client "sappia" quando smettere di leggere righe.

    Originariamente inviato da ilblondobari86
    Ho provato a fare una chiamata con il telnet al mio server e questo riesce a ricevere anche più righe per volta senza che il mio server indichi quando ha finito di "parlare". Come fa?
    Come fa? Semplice .... lui non "sa" certo quante righe aspettarsi. Tu vedi un cursore, che è il punto in cui tu puoi scrivere. Se il telnet riceve "qualcosa", lo stampa e sposta il cursore. Insomma, il cursore si sposta se tu scrivi O se lui riceve e stampa qualcosa. Ma lui appunto non "sa" nulla di quanto/cosa riceve!!

    Prova a far inviare dal server un tot di righe, intervallate da uno sleep di mezzo secondo e ... capirai!

    Originariamente inviato da ilblondobari86
    O un server http, ad esempio, che risponde con un'intera pagina http e non con una sola riga come funziona?
    HTTP è diverso. Nella response ci sono tipicamente header+body e tra gli header viene inviato un Content-Length.

    Originariamente inviato da ilblondobari86
    Nel mio progetto c'è una classe server che ascolta sulla porta num e ogni qualvolta si connette un client chiama un thread che gestisce la comunicazione con il client.
    Il thread server poi chiama un altro thread nel caso in cui gli venga chiesto di fare un'altra operazione particolare (che nel caso in particolare è uno scanner di una pagina). Ora, questo sotto thread come fa a spedire la risposta al giusto client?
    Ho pensato di inserire ogni socket del client in un vettore. Poi, però, non so nel sotto thread, quando devo dare la risposta a prendere la socket che l'ha invocato...
    Non so se sono stato chiaro. Se avete bisogno posto il codice.
    Purtroppo non mi è chiarissimo cosa devi fare e perché.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Grazie infinite!
    Allora... penso che risolverò il problema della comunicazione di più righe inviando dal server il numero di righe che devono essere lette(ho chiaro il concetto ma lo realizzerò oggi pomeriggio)e ovviamente il client leggerà il numero di righe inviate dal server.
    Non mi piace molto come soluzione, preferivo che il client capisse quello che il server inviava finchè non "smetteva" di inviare...
    Il carattere di fine "marker" risolverebbe questo problema ma non saprei assolutamente che carattere mettere poichè, per esempio,se impostassi come linea "marker" ad esempio
    "END"
    e volessi inviare al client una riga proprio "END" non come "marker" questo ovviamente non lo leggerebbe e concluderebbe il ciclo.

    Poi per il secondo problema cerco di spiegarlo meglio con esempi.

    Se avessimo un server che risponde al client con i risultati di operazioni matematiche,
    il server thread ad una richiesta di un client come "SUM" effettua l'operazione di somma e restituisce il risultato.
    Se ad una richiesta di tipo "FATTORIALE" il server thread non calcola direttamente il fattoriale ma rimanda il calcoload un altro sottothread.
    Ora, questo sottothread come fa a dare il risultato al client?
    Lo ridà al server thread che l'ha invocato? o al client?
    come riconosce il client nel caso che debba dare il risultato a questo?
    Se non sono stato ancora chiaro faccio un esempio con le classi realizzate

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da ilblondobari86
    preferivo che il client capisse quello che il server inviava finchè non "smetteva" di inviare...
    E come farebbe??? Vedilo idealmente come se fosse una comune conversazione telefonica. Stai parlando con una persona e gli hai posto una domanda. L'altro si mette a rispondere però ogni tanto fa delle brevi pause .... come potresti capire, in generale, se ha finito la risposta??? O "riaggancia" (equivalente ad un close() in Java) e quindi capisci che ha terminato oppure l'altro potrebbe dirti: "c'è altro?".

    Beh, certo .... in una comunicazione "reale" al telefono non è proprio così nel senso che dal tono, dal discorso uno deduce quando l'altro ha terminato di dire qualcosa. Ma vedilo molto "idealmente" come ho detto.

    Originariamente inviato da ilblondobari86
    Il carattere di fine "marker" risolverebbe questo problema ma non saprei assolutamente che carattere mettere poichè, per esempio,se impostassi come linea "marker" ad esempio
    "END"
    e volessi inviare al client una riga proprio "END" non come "marker" questo ovviamente non lo leggerebbe e concluderebbe il ciclo.
    Ma non è certo l'unica soluzione!!!
    La linea di marker potrebbe contenere un carattere non stampabile, ad esempio un carattere ASCII codice 3 (che in ASCII significa guarda caso "End of Text") in una stringa "\003".

    Oppure potresti avere un carattere all'inizio di ogni riga che indica una informazione e una riga vuota alla fine:

    "%BlaBla"
    "%BloBlo"
    "" (riga vuota)

    Una riga vuota indica la fine. Le altre righe non saranno mai vuote in quanto avranno sempre un % davanti (e tu prenderai solo dal secondo carattere per avere la "vera" informazione).

    Altra variante di questo approccio: metti sempre un carattere davanti ma cambia per indicare l'ultima riga:

    "%Blabla"
    "#BloBlo"

    La riga che inizia con # è l'ultima.

    Come vedi puoi inventarti tutto quello che vuoi!!
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Risolto!
    Grazie mille!
    Ho fatto inviare al server un carattere di fine testo (il 3 nella tabella ascii) come suggerito da te e il client legge fin quando non trova questo bel carattere.
    Funziona molto bene o per lo meno fa quel che volevo.
    Ora ho un altro problema... però magari apro un altro thred apposito...
    Grazie ancora...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.