Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 14
  1. #1

    [Java] Invio dati a Thread diversi

    Ciao a tutti.

    Sto realizzando un piccolo giochetto online... dove ho costruito un client in Flash e un Application Server in Java.

    Il lavoro sembra andare a meraviglia... il client fa login sull'Application Server, seleziona la tipologia di gioco etc. Per ogni client si collega, creo un Thread diverso che si occupa di ricevere i dati dal client e di spedirne di nuovi.
    Quindi il tutto funziona a meraviglia se un client specifico chiede qualcosa al server e riceve una risposta direttamente.

    Il problema nasce quando un client A fa una richiesta al server... e successivamente alla richiesta l'ApplicationServer deve spedire una risposta a tutti (o parte di essi) i client.
    Questa cosa non riesco a farla.. riesco solo al rispondere al client che mi invia una richiesta... ma non so inviare una risposta a più client contemporaneamente.

    Sapreste dirmi come procedere?

    Grazie mille per l'aiuto

    Questo è il codice commentato. L'ultima funzione che vedete (fai_qualcosa) dovrebbe inviare dei dati ad alcuni dei client. Ma non ci riesco.

    codice:
    /*
     * DICHIARAZIONE DELLE VARIABILI GLOBALI
     */
     // Creo un istanza Thread per il Listener delle connessioni.
     // Ho messo il listener in un Thread a parte per evitare che il software resti congelato
     SocketListenerThread socketListener = new SocketListenerThread();
     
    
    /*
    * THREAD
    * Che si occupa di gestire l'ascoltatore delle connessioni
    */
    class SocketListenerThread extends Thread {    
        @Override
        public void run() {
            try {
                // Avvio l'ascoltatore per le connessioni
                ServerSocket serverSocket = new ServerSocket(5432); 
                // Avviso che il server è Online
                // IL SERVER è ORA IN ASCOLTO
                //Ciclo infinito di ascolto delle connessioni dei client
                while(true) {
                    // L'Accept si occupa di accettare le connessioni in ingresso.
                    // Il thread resta fermo fino a quando non si collega un client
                    Socket socket = serverSocket.accept();
                    // Collegato un client, creo un nuovo Thread nel quale apro un socket per questo client
                    SocketThread socketThread = new SocketThread(socket);
                    // Eseguo il codice di inzializzazione del Thread
                    socketThread.start();                    
                 }
             }catch(IOException ioe){
                 // Se si verifica un errore del Listener
                 // Mostro un avviso          
             }
         }
    }
     
     
     
     
    /* 
     * SOCKET
     * Creazione di una classe per il Multrithreading
     */
    class SocketThread extends Thread  {
        // Creo il socket per il client che si è appena connesso
        private Socket socket;
        // Creo le variabili che contengono i dati del Client
        private String socket_name;
        // Creo un metodo di inizializzazione del socket
        public SocketThread (Socket socket) {
           // Copio il socket creato in fase di connessione del client, nel socket di questo Thread
           this.socket = socket;
        }
            
        //esecuzione del Thread sul Socket
        @Override
        public void run() {
            try {
                // Creo un DataInputString per ricevere le stringhe dei dati inviate dai Client
                BufferedReader socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                // Creo un PrintStram per inviare stringhe ai client
                 PrintStream os = new PrintStream(socket.getOutputStream());
                // Creo un ciclo infinito per prelevare i comandi del Client ed eseguirne le operazioni
                // Solo nel momento in cui il Client eseguirà il Logout, chiuderò il ciclo
                while(true) {
                     try {
                         // Resto in attesa di una stringa inviata dal Client
                         //String userInput = is.readLine();
                         String userInput = socketIn.readLine();
                         // Ricevuta la stringa, la ripulisco da dati nulli all'inizio e alla fine
                         userInput = userInput.trim();
                         // Verifivo il comando inviato dal Client, per eseguire le operazioni richieste
                         if (userInput.equals("logout") == true) {
                         	break;
                         } else if (userInput.equals("fai_qualcosa") == true) {
                         	fai_qualcosa();
                         }
            	     } catch (Exception e) {
                     	// Si è verificato un errore
                        break;
            		}
        		}
        		// Il Client ha eseguito il Logout
        		// Chiudo il DataInputString e il PrintStream
        		os.close();
        		socketIn.close();
        		// Chiudo il Socket della connessione
        		socket.close();
    		} catch (IOException e) {
               // Si è verificato un errore
            }
       }
    }
    
    
    
    
    
    
    public void fai_qualcosa() {
    	
    	// COME SPEDISCO UN RISULTATO A TUTTI I CLIENT???
    	
    	// DEVO SPEDIRE UN MESSAGGIO AD OGNI THREAD DEI CLIENT...
    
    }

  2. #2
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    1,123
    Scusami se non leggo il codice, ma ho alcuni problemi alla vista questa sera.

    Ho letto però il tuo problema. Direi sia affrontabile facendo in questo modo:
    Esempio:
    Hai una classe Server che gestisce tutti i Client che si connettono. Alla connessione di un Client crei un oggetto, incaricando all'invio ed alla ricezione di messaggi con quel client. Questo oggetto che crei non lo butti ovviamente, lo inserisci in un ArrayList. Quando riceverai un messaggio (o richiesta insomma) da parte di un client, non ti resterà che scorrere l'elenco di Client all'interno dell'ArrayList situato nella classe Server.

    Credo di essermi spiegato, ma se qualcosa non è chiaro chiedi pure. Magari avrai anche altri pareri

  3. #3
    Utente di HTML.it
    Registrato dal
    Feb 2007
    Messaggi
    4,157
    c'è una considerazione da fare: tu comunichi via socket (fin qui niente di strano) tra un client e un server. In genere si fa la connessione, si gestisce la comunicazione e si chiude. Quello che dici tu lo puoi fare in 2 modi:
    1. come ti è stato suggerito tieni un pool di connessioni (in un hashmap per un accesso rapido). Ma devi gestire errori nella rete (timeout, disconnessioni ecc)
    2. apri una comunicazione tra server e client, ma qui subentrano problemi di firewall e simili.

    Mi chiedo, è davvero necessario questo polling di tutti i client? non si può fare un upadte dello stato alla prox richiesta?

  4. #4
    Ciao.

    Grazie mille per le risposte.

    x Patrick: Si ho capito come dovrei fare... il mio problema è prioprio l'implementazione. Non capisco bene come farla. In pratica io dovrei creare un vettore PUBBLICO di oggetti PrintStream... e ogni volta che si collega un client dovrei metterci l'oggetto socket.getOutputStream di quel client. Giusto?
    Potreste magari farmi un esempio con il codice... con questo vettore...

    x valia: Riguardante la gestione di disconnessioni, etc... ho già implementato qualcosa, quindi non dovrebbero esserci problemi da quel punto di vista.
    Fare un update ad ogni richiesta... direi che non riesco. Perchè ammettiamo che abbiamo i client A, B, C, D. Tutti devono spedire un "update" di alcuni dati... il server elabora TUTTI gli update spediti da questi 4 client e dopo deve spedire il risultato a tutti.

  5. #5
    Utente di HTML.it
    Registrato dal
    Feb 2007
    Messaggi
    4,157
    no no non mi hai capita.
    Sono l'utente A e navigo traquilla. L'utente B fa delle modifiche. Tu con questo sistema di polling aggiorni B e subito dopo aggiorni A. Ma è davvero necessario aggiornare subito A? Non è più semplice aggiornare A nell'istante in cui fa una richiesta (fermo restando le considerazioni minime di implementazione).

  6. #6
    Originariamente inviato da valia
    no no non mi hai capita.
    Sono l'utente A e navigo traquilla. L'utente B fa delle modifiche. Tu con questo sistema di polling aggiorni B e subito dopo aggiorni A. Ma è davvero necessario aggiornare subito A? Non è più semplice aggiornare A nell'istante in cui fa una richiesta (fermo restando le considerazioni minime di implementazione).
    Mmm... secondo me per quello che devo fare, non posso fare come dici.
    Nel senso, ammettiamo che abbiamo A, B e C che sono dei personaggi con dei punti vita (facciamo 100 a testa), e stanno combattendo contro un mostro -_-
    Nel momento in cui il mostro toglie 20 punti a B... A e C devono vedere B a 80 quando succede.. non quando magari fanno loro una mossa.

    E che dovrei spiegarti tutto il progettino del gioco. Secondo me quello che mi consigli è giustissimo... ma nel mio caso non saprei bene come implementarlo. Preferirei spedire dei dati a tutti i client anche senza una specifica richiesta.

  7. #7
    Utente di HTML.it
    Registrato dal
    Feb 2007
    Messaggi
    4,157
    ok allora vada per il pool di connessioni, ovviamente devi gestire bene le connessioni, soprattutto non chiudere il socket dopo una operazione (perdi il riferimento allo stream su cui scrivi)

  8. #8
    Originariamente inviato da valia
    ok allora vada per il pool di connessioni, ovviamente devi gestire bene le connessioni, soprattutto non chiudere il socket dopo una operazione (perdi il riferimento allo stream su cui scrivi)
    Ooook. Ora faccio una prova a creare un ArrayList pubblico e ogni volta che un client si connette ci metto dentro l'oggetto del PrintStream.
    Da quel che ho capito devo fare così.

    Vabbè, provo (ovviamente) e vi faccio sapere



    PS: Oh, comunque grazie per le risposte, gentilissimi

  9. #9
    Chiedo scusa per il doppio post ma... mi sono bloccato

    Allora io mi sono creato questo:

    codice:
    ArrayList client_socket = new ArrayList();
    int client_socket_index = 0;
    Il primo è l'ArrayList che contiene gli oggetti dei client per spedire le stringhe, mentre il secondo è un semplice contatore per sapere dove va inserito il prossimo.

    Poi faccio:

    codice:
    client_socket.add(new PrintStream(socket.getOutputStream()));
    client_socket_id = client_socket_index;
    client_socket_index = client_socket_index +1;
    Quindi quando uno si connette... nel ArrayList ci finisce l'oggetto del PrintStream collegato suo socket. Poi mi creo una variabile ID (privata) che per ogni socket ne indica la posizione del proprio PrintSteam.
    Infine aumento il contatore.

    Fin qui tutto bene... bello, fantastico...

    Il problema giunge quando devo usare gli oggetti che sono inseriti nell'ArrayList. Ammettiamo che devo spedire un messaggio al client con ID 24... io faccio così:

    codice:
    client_socket.get(24).println("MESSAGGIO\u0000");
    Oppure se devo spedirlo al client che mi ha inviato un comando:

    codice:
    client_socket.get(client_socket_id).println("MESSAGGIO\u0000");

    Peccato che queste 2 righe di codice che vi ho scritto non funzionano. In quanto println non viene riconosciuto.

    Quindi la mia domanda è... come faccio ad usare dei metodi di un oggetto contenuto nell'ArrayList?

    Grazie per le risposte.

  10. #10
    Il problema che ArrayList dichiarato come hai fatto tu ritorna indietro un Object e non u printStream. Le soluzioni sono due :
    Da Java 5 in poi, tutte le collection sono Generiche e quindi basta tipizzarle la momento della creazione. Es.
    codice:
    ArrayList<OutputStream> client_socket = new ArrayList<OutputStream>();
    In questo modo quando invocherai il metodo "get" ti verrà restituito un OutputStream e non un Object (ovviamente dentro l'array list potrai metterci solo oggetti OutputStream o sottoclassi di esso).
    Se invece stai usando un vecchia versione di Java allora non ti resta che fare un cast esplicito. Es:
    codice:
     
    ((ObjectOutputStream)client_socket.get(24)).println("MESSAGGIO\u0000");
    //Meglio controllare che effettivamente esso sia un ObjectOutputStream prima di castarlo
    Object tmp = client_socket.get(24);
    if(tmp instanceof ObjectOutputStream)
    {
    ((ObjectOutputStream)tmp).println("MESSAGGIO\u0000");  
    }
    Ciauz:

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.