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

    problema con piccola chat tra server e client (socket)

    Salve, giusto qualche giorno fa ho ultimato il mio server e il mio client che, connessi tra loro attraverso i sockets, si scambiano messaggi. Quelle applicazioni, tuttavia, non erano applicazioni grafiche(console) e quindi ho deciso adesso di dargli una grafica. Desso ho un problema per quanto riguarda il server. Metto le tappe che ho fatto:

    1) costruisco un JButton che, una volta cliccato, fa avviare un thread che crea il server alla porta 6000 e attende che un client vi acceda.
    Inoltre creo (lo dico a parole mie, scusate i miei termini scarni) un oggetto della classe OutputStream con parametro Il Client. Adesso faccio vedere il pezzo di codice
    codice:
    OutputStream out = client.getOutputStream();
    Fin qui non c'è problema

    2) costruisco una JFieldText e un JButton. Alla pressione di questo bottone, il programma manda in esecuzione un altro Thread. Creo una String mess alla quale do il valore della textField attraverso un costruttore e poi creo un oggetto di PrintStream con parametro out (che si trova in un'altra classe) facendo così
    codice:
    prova2 prov = new prova2(); // prova2 è la classe che contiene out
    p = new PrintStream(prov.out); 
    		p.println(mes); //mes =  la variabile che contiene il contenuto della JFieldText
    ora, sapendo che il messaggio contenuto nella JFieldText arriva effettivamente alla variabile mess (ho provato a mettere un System.out.printl(mess)), perchè il compilatore mi indica come sbagliata p = new PrintStream(prov.out); ????

    se volete vi posto tutti i codici

    ecco il thread che contiene la connessione e la dichiarazione di OutputStream out. Il suo nome è prova2

    codice:
    package serververo;
    
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    import javax.swing.JOptionPane;
    
    public class prova2 implements Runnable{
    ServerSocket server;
    Socket client;
    OutputStream out;
    	@Override
    	public void run() {
    		try {
    			server = new ServerSocket(6000);
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		    client = new Socket();
    		   
    		   JOptionPane.showMessageDialog(null, "connessione effettuata con successo, attesa del client...");
    		    try {
    				client = server.accept();
    				out = client.getOutputStream();
    			} catch (IOException e) {
    				
    				e.printStackTrace();
    			}
    		    JOptionPane.showMessageDialog(null, "un client si è collegato");
    		   
    			}
    		
    	}
    e qui c'è il thread riguardante la scrittura del messaggio (PrintStream), il nome ddella classe è prova

    codice:
    package serververo;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.PrintStream;
    
    
    
    public class prova implements Runnable {
    	String mes;
    	
    	PrintStream p;
    	public  prova(String mess) throws IOException
    	{
    		this.mes = mess;
    	}
    
    	@Override
    	public void run() {
    		
            prova2 prov = new prova2();
            System.out.println(mes);
    		p = new PrintStream(prov.out);
    		p.println(mes);
    		
    	}
    
    
    }
    infine ecco il codice della finestra grafica

    codice:
    package serververo;
    
    import java.awt.BorderLayout;
    
    public class server extends JFrame {
    	
        OutputStream output;
        InputStream input;
        BufferedReader leggi;
        PrintStream scrivi;
        
    	private JPanel contentPane;
    	private JTextField textField;
    
    	/**
    	 * Launch the application.
    	 */
    	public static void main(String[] args) {
    		EventQueue.invokeLater(new Runnable() {
    			public void run() {
    				try {
    					server frame = new server();
    					frame.setVisible(true);
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		});
    	}
    
    	/**
    	 * Create the frame.
    	 */
    	public server() {
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		setBounds(100, 100, 547, 408);
    		contentPane = new JPanel();
    		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    		setContentPane(contentPane);
    		
    		final JButton btnConnetti = new JButton("connetti");
    		btnConnetti.addMouseListener(new MouseAdapter() {
    			@Override
    			public void mouseClicked(MouseEvent arg0) {
    				prova2 connessione = new prova2();
    				Thread connect = new Thread(connessione);
    				connect.start();
    				    
    			}
    		});
    		
    		textField = new JTextField();
    		textField.setColumns(10);
    		
    		JButton btnInviaMessaggio = new JButton("INVIA MESSAGGIO");
    		btnInviaMessaggio.addMouseListener(new MouseAdapter() {
    			@Override
    			public void mouseClicked(MouseEvent arg0) {
    			try {
    				String messaggio = textField.getText();
    				prova Prova = new prova(messaggio);
    				
    				Thread proviamo = new Thread(Prova);
    				proviamo.start();
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    			}
    		});
    		
    		JTextArea textArea = new JTextArea();
    		GroupLayout gl_contentPane = new GroupLayout(contentPane);
    		gl_contentPane.setHorizontalGroup(
    			gl_contentPane.createParallelGroup(Alignment.LEADING)
    				.addGroup(gl_contentPane.createSequentialGroup()
    					.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING)
    						.addGroup(gl_contentPane.createSequentialGroup()
    							.addGap(25)
    							.addComponent(btnConnetti))
    						.addGroup(gl_contentPane.createSequentialGroup()
    							.addContainerGap()
    							.addComponent(textField, GroupLayout.DEFAULT_SIZE, 501, Short.MAX_VALUE))
    						.addGroup(gl_contentPane.createSequentialGroup()
    							.addGap(210)
    							.addComponent(btnInviaMessaggio)))
    					.addContainerGap())
    				.addComponent(textArea, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 531, Short.MAX_VALUE)
    		);
    		gl_contentPane.setVerticalGroup(
    			gl_contentPane.createParallelGroup(Alignment.LEADING)
    				.addGroup(gl_contentPane.createSequentialGroup()
    					.addContainerGap()
    					.addComponent(btnConnetti)
    					.addPreferredGap(ComponentPlacement.RELATED)
    					.addComponent(textArea, GroupLayout.PREFERRED_SIZE, 238, GroupLayout.PREFERRED_SIZE)
    					.addPreferredGap(ComponentPlacement.RELATED, 7, Short.MAX_VALUE)
    					.addComponent(textField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
    					.addGap(18)
    					.addComponent(btnInviaMessaggio)
    					.addGap(13))
    		);
    		contentPane.setLayout(gl_contentPane);
    	}
    }
    tutto si può fare, bisogna solo volerlo
    http://italybrain.altervista.org/

  2. #2
    Utente di HTML.it
    Registrato dal
    May 2007
    Messaggi
    55
    Ciao,
    quindi stai dicendo che non riesci a compilare perché ti da problemi l'istruzione
    codice:
    p = new PrintStream(prov.out)
    Strano, a me sembra corretta, prova a postare l'errore.

  3. #3
    ok

    Exception in thread "Thread-3" java.lang.NullPointerException: Null output stream
    at java.io.PrintStream.requireNonNull(Unknown Source)
    at java.io.PrintStream.<init>(Unknown Source)
    at java.io.PrintStream.<init>(Unknown Source)
    at serververo.prova.run(prova.java:23)
    at java.lang.Thread.run(Unknown Source)

    la riga 23 è proprio quella, ma non capisco il motivo dell'errore.

    Grazie per l'interesse

    tutto si può fare, bisogna solo volerlo
    http://italybrain.altervista.org/

  4. #4
    Utente di HTML.it
    Registrato dal
    May 2007
    Messaggi
    55
    Quindi quello è un errore di Runtime! La compilazione non da problemi.
    Riguardando il run della classe prova (in genere in java i nomi delle classi sono con la prima maiuscola: Prova), tu inizializzi un prova2, e usi subito il suo attributo out. Ma in quel punto è chiaro che out è nullo, l'oggetto prov non c'entra niente con quello "connessione" creato nella classe "server".
    Forse dovresti rivedere un po' di logica del sistema. Tra l'altro, chi è il client che dovrebbe connettersi al server? Sempre in prova2 lanci un
    codice:
    client = server.accept();
    Finché un client non si connette, il thread resta bloccato li, dove è la connessione del client?

  5. #5
    per quanto riguarda il client, ho utilizzato un client che avevo scritto precedentemente, un semplice client senza grafica, che si connette al server e può inviargli messaggi. La connessione avviene, ma il problema è stato appunto mandare un messaggio da server a client. Il client ultimato (utilizzando le swing) lo farò una volta che ho capito che il sistema funziona. Tuttavia non ho capito la parte che l'out è nullo. Infatti, una volta che connetto il client, mi esce l'avviso: "un client si è collegato", quindi se è arrivato a quel punto significa che l'out ha preso il proprio valore... infatti io utilizzo l'out solo dopo che il client si sia collegato. Comunque, se ho appena detto una stupidata (come credo di aver fatto) correggimi e magari, mi potresti suggerire quindi dove lo devo mettere la dichiarazione dell'out?

    Grazie mille


    tutto si può fare, bisogna solo volerlo
    http://italybrain.altervista.org/

  6. #6
    Utente di HTML.it
    Registrato dal
    May 2007
    Messaggi
    55
    Quando clicchi su "Invia messaggio", istanzi un nuovo oggetto prova che poi "esegui" con
    codice:
    proviamo.start();
    Il run fa le seguenti cose, scrivo tra i commenti, forse è più chiaro
    codice:
    /*crei un oggetto di tipo prova2 che non ha niente a che fare con quello di prima in cui gestisci
    le connessioni del server, per intenderci quello che ti ha stampato "un client si è collegato" */
    prova2 prov = new prova2(); 
    System.out.println(mes);//stampi il messaggio
    p = new PrintStream(prov.out); //prov.out è nullo, l'oggetto prov è stato appena creato!
    p.println(mes);
    Questo per quanto riguarda l'errore che ottieni. Sul funzionamento non so bene cosa suggerirti, non ho capito cosa vuoi ottenere: mandare messaggi dal server verso i client? Non mi sembra proprio una chat...

  7. #7
    Grazie, adesso ho capito!!! Comunque, adesso sto ancora facendo la parte che invia i messaggi dal server al client, dopo farò la parte in cui il server riceve messaggi dal client(per questo chat, più che altro una pseudo chat).
    Tornando all'errore, quindi, dove devo mettere la dichiarazione dell'OutputStream?

    Grazie

    tutto si può fare, bisogna solo volerlo
    http://italybrain.altervista.org/

  8. #8
    EDIT.

    No, alla fine ho capito di non capire
    Anche se l'oggetto lo ho comunque creato subito, 'out' ha un contenuto nella classe prova2. Quindi, anche se l'oggetto lo ho appena creato, do come parametro a p (sarebbe PrintStream) l'out, che non è vuoto, in quanto lo ho preso da un'altra classe che ormai ha terminato il suo compito. Quindi non riesco a capire perchè sia nullo, cme faccio a non renderlo nullo???
    tutto si può fare, bisogna solo volerlo
    http://italybrain.altervista.org/

  9. #9
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Cerco di spiegarti prima perchè quell'oggetto è nullo, poi qual è il tuo reale problema.

    Perchè l'oggetto out è nullo
    Come ti ha giustamente fatto notare borras, tu crei un nuovo oggetto "prova2". Tutte le variabili di istanza di questo nuovo oggetto, all'atto della sua creazione, sono nulle perchè, spero ti sia chiaro, ciascuna istanza ha le proprie variabili i cui valori non hanno nulla in comune con quelle delle eventuali altre istanze. L'oggetto "out" di una istanza di "prova2" viene inizializzato solo all'interno del metodo run(), quindi ciascuna istanza di "prova2" deve eseguire il metodo run() per far sì che il suo oggetto "out" venga inizializzato. Il metodo run() viene invocato tramite la chiamata al metodo "start()", essendo un thread. Quindi, per poter inizializzare l'oggetto out di un'istanza di "prova2" è necessario che su questa istanza venga richiamato il metodo start(). E tu non lo stai facendo.

    Ti mostro in termini di codice e commenti questa cosa:
    codice:
    // Creo diverse istanze di "prova2"
    prova2 p1 = new prova2();   // Il suo oggetto "out" è nullo
    prova2 p2 = new prova2();   // Il suo oggetto "out" è nullo
    prova2 p3 = new prova2();   // Il suo oggetto "out" è nullo
    
    p1.start();   // Ora il suo oggetto "out" è valorizzato
    
    // Gli oggetti "out" di p2 e p3 sono ancora nulli!
    Detto questo, non farti prendere dalla tentazione di "risolvere" chiamando la start() sul nuovo oggetto "prova2" perchè non risolveresti proprio nulla, ma al contrario peggioreresti la situazione. Leggi qui di seguito.

    Il tuo reale problema
    Il tuo problema reale non ha nulla a che vedere con il fatto che "out" è nullo: il problema più grosso sta a monte. Non devi creare una nuova istanza di "prova2", ma devi poter utilizzare quella che hai già istanziato e correttamente inizializzato nella classe "server". Quindi, in qualche modo, la classe "prova" deve ricevere un riferimento all'oggetto "prova2" creato nella classe "server" e non deve fare una "new" (che significa, appunto, "crea una nuova istanza"). Questo riferimento lo puoi passare al costruttore o ad un metodo che dovrai provvedere a creare.
    In soldoni, il problema è il passaggio di parametri tra una classe e l'altra ed è questo concetto che devi rivedere.

    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  10. #10
    Grazie molte, il mio problema nella comprensione è stato il fatto che, non potendo andare in una scuola apposita, ho dovuto imparare da solo, con guide su internet, quindi io pensavo che creando un oggetto e con quest ultimo prendendo una variabile di un'altra classe, possa prendere il valore dell'altra classe. Per quanto riguarda il problema a monte, dovrei
    1) creare un oggetto di "prova" nella classe "prova2"

    2) richiamare il metodo di "prova" passando come valore il client

    3) out non sarà più nullo.

    Giusto?

    Grazie

    tutto si può fare, bisogna solo volerlo
    http://italybrain.altervista.org/

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.