Newsgroup: it.comp.java
Titolo: [w2k|jdk1.2.2] Cos'è uno scherzo?

  Così per gioco mi sono fatto un semplice client POP3 con il JDK 1.2.2 su
windows 2000. 
Ad ogni lettura di riga (readLine) da un BufferedReader verifico la
disponibilità di caratteri in lettura con la funzione ready() che mi funge
da condizione di permanenza nel ciclo while.
  Le cose non vanno come vorrei, nel senso che la lettura si blocca anche
se effettivamente ci sono caratteri sul buffer (le letture successive
sullo stesso cnanale input lo evidenziano!). Allora vado a leggere bene la
doc della classe progenitrice ... funzione Reader.ready() ...e ... insomma
vi prego leggete anche voi e ditemi se non è follia.
  Forse il folle sono io? Se sì, mi indicate come si usano questi
benedetti java.net.Socket e canali java.io.* connessi?
grazie anticipate.
Alx
 
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 windows 2000.
Perchč usi la 1.2.2 (siamo alla 1.5) ?
-- 
Consonni Davide
(
dcon...@enter.it
)

 Perchè usi la 1.2.2 (siamo alla 1.5) ?
Dai, ufficialmente siamo alla 1.4... la 1.5 è ancora in beta... :))
	Regards,
		Kazuma
-- 
Alessandro "Kazuma" Garbagnati, kazuma(presso)jguru(punto)com
Tomcat & EJB FAQ Manager, 
http://www.jguru.com

 vi prego leggete anche voi e ditemi se non è follia.
Perché follia?
La documentazione di
    public boolean ready() throws IOException
dice:
   Tell whether this stream is ready to be read.
   Returns:
     True if the next read() is guaranteed not to block for input,
     false otherwise. Note that returning false does not guarantee
     that the next read will block.
   Throws:
     IOException - If an I/O error occurs
Qual`è il problema?
Se ready() torna true puoi fare con successo una read.
Non è quello che vuoi?
- Dario

Ciao, Dario!
Il giorno 20/04/2004 alle ore 18:47 hai scritto:
 Dc>    Returns:
 Dc>      True if the next read() is guaranteed not to block for input,
 Dc>      false otherwise. Note that returning false does not guarantee
 Dc>      that the next read will block.
 Dc>    Throws:
 Dc>      IOException - If an I/O error occurs
 Dc>
 Dc> Qual`è il problema?
 Dc> Se ready() torna true puoi fare con successo una read.
 Dc> Non è quello che vuoi?
Non e' esattamente cosi': se ritorna true significa che una successiva read
non blocchera' il programma perche' i dati sono subito disponibili, mentre
se ritorna false la successiva read potrebbe bloccare il programma finche'
non saranno disponibili i dati da leggere, questo non e' garantito perche' i
dati potrebbero arrivare dopo la verifica di ready e prima della read.
Non e' follia e' il semplice funzionamento normale dei socket. Con i socket
non puoi sapere se i dati da ricevere sono terminati o meno perche' questo
tipo di informazione non viene passata. Per sapere se i dati sono terminati
e' necessario verificare quando il socket viene chiuso oppure incapsulare i
dati in una struttura che passi anche la dimensione dei dati stessi.
Utilizzando BufferedReader si puo' verificare se readLine() ritorna null nel
qual caso lo stream e' terminato.
Bye
-- 
Marco Maccaferri
MaccaSoft - 
http://www.maccasoft.com

 Perchè usi la 1.2.2 (siamo alla 1.5) ?
Perché è leggera. 
Quanto pesa la 1.5? Non dirmelo... già mi viene da ridere :-)
Seriamente parlando,
a tutti i miei clienti consiglio sempre un downgrade software
e hardware. Perché sprecare risorse e denari, quando tutto ciò di
cui il mondo ha bisogno può essere sviluppato con un jdk 1.2.2?
Saluti,


rotfl.
-- 
Consonni Davide
(
dcon...@enter.it
)

 Bye
In effetti anch'io ricordavo qualcosa del genere ma non ha funzionato,
a quanto pare funziona meglio ready(), mentre il test di uguaglianza a null
è sempre bloccante.
Riporto il sorgente per completezza.
Da notare che il programello gira perfettamente così com'è, ma se
lanciassi un comando LIST invece che LAST:
			//request("LAST\n");
			request("LIST\n");
Il risultato sarebbe di riuscire a leggere solo una riga della risposta
dal server. Boh!
---------------------------SORGENTE
import java.io.*;
import java.net.*;
class MailCleaner {
	static Socket s = null;
	static InputStream is = null;
	static OutputStream os = null;
	static BufferedReader br = null;
	static InputStreamReader isr = null;
	static URLConnection uc = null;
	public static void main(String argv[]) {
	  if (argv.length < 4) {
	    System.out.print(
	      "USAGE:   java MailCleaner 
my.host.com
 user password
message_count\n"+
              "Example: java MailCleaner 
www.yahoo.com
 john.holmes secret
678\n"
	    );
	    return;
	  }
	  try {
	    // vars
	    int i = Integer.parseInt(argv[3]);
	    s = new Socket(argv[0], 110);
	    os = s.getOutputStream();	        
	    is = s.getInputStream();
    	    isr = new InputStreamReader(is);
    	    // body
    	    welcome();
            request("USER "+argv[1]+"\n");
	    request("PASS "+argv[2]+"\n");
	    for (; i>0; i--) {
	      request("DELE "+i+"\n");
	    }
	    request("LIST\n");
	    request("QUIT\n");
            // close
	    isr.close();
	    is.close();
	    os.close();
	  } catch(Exception e) {
	    e.printStackTrace();
	  }
	}
    private static void welcome() throws Exception {
      String line = null;
      br = new BufferedReader(isr);
      // receive
      do { 
	line = br.readLine();
	System.out.println(line);
      } while (br.ready());
      /*
      while ((line = br.readLine()) != null) {
        System.out.println(line);
      }
      */
      // close: commentato perché la chiusura da problemi
      //br.close();
    }
 
    private static void request(String str) throws Exception {
      String line = null;
      br = new BufferedReader(isr);
      // send
      System.out.print(str);
      os.write(str.getBytes());
      // receive
      do {
	line = br.readLine();
	System.out.println(line);
      } while (br.ready());
      /*
      while ((line = br.readLine()) != null) { 
        System.out.println(line);
      } 
      */
      // close: commentato perché la chiusura da problemi
      //br.close();
    }
  }
------------------------FINE SORGENTE
Insomma non c'è modo di leggere sul canale di input senza bloccarsi?
Grazie dell'attenzione,


Ciao, Alx!
Il giorno 21/04/2004 alle ore 14:21 hai scritto:
 A> Riporto il sorgente per completezza.
 A> Da notare che il programello gira perfettamente cosě com'č, ma se
 A> lanciassi un comando LIST invece che LAST:
Il programma gira perfettamente solo per puro caso, perche' stai usando le
funzioni nel modo sbagliato, lo dimostra il fatto che con LIST, con cui
ottieni piu' di una riga, non funziona.
Cito solo il loop del metodo request:
 A>       // receive
 A>       do {
 A>  line = br.readLine();
 A>  System.out.println(line);
 A>       } while (br.ready());
Al primo readLine il socket si blocca in attesa di ricevere dei dati, anche
se tu non te ne accorgi, una volta letti, ready() ritorna ovviamente false
perche' il server non manda piu' niente e quindi non c'e' niente nel buffer
(questo ovviamente vale solo per i comandi USER, PASS, DELE e QUIT che
rispondono generalmente con una sola riga). Il loop fallisce miseramente il
suo compito quando tenti di utilizzare LIST che produce piu' linee di
output, nel passare da readLine() a ready() il buffer continua ad essere
vuoto e quindi esce subito. Questo e' comunque un puro caso e ci sono molti
fattori che possono determinare comportamenti anche molto diversi (come ad
esempio leggere solo le prime 6-7 righe e poi uscire) e dipende sia dalla
velocita' della macchin client che da come e' stato realizzato il server
remoto.
 A>       /*
 A>       while ((line = br.readLine()) != null) {
 A>         System.out.println(line);
 A>       }
 A>       */
Questo, che e' teoricamente corretto, si blocca perche' non c'e' una
condizione di uscita. readLine() ritorna null quando il socket viene chiuso
non quando tu pensi che i dati siano finiti. Come ho detto con i socket non
c'e' modo di sapere se i dati sono finiti, se non c'e' un protocollo nel
mezzo che lo determina. Nel caso di LIST, per esempio, la lista finisce con
una riga contenente un punto. Negli altri casi ci sono i metodi per sapere
se l'output e' ad una riga oppure a piu' righe nell'RFC relativo all'FTP.
 A>       // close: commentato perché la chiusura da problemi
 A>       //br.close();
Ovvio, chiudendo il socket non potrebbe essere altrimenti...
 A> Insomma non c'č modo di leggere sul canale di input senza bloccarsi?
Consiglierei un piu' attento studio della materia.


 Insomma non c'è modo di leggere sul canale di input senza bloccarsi?
La tua condizione di uscita dai tuoi while è sbagliata.
Infatti tu esci dal while in funzione del carico della rete
invece che in funzione del protocollo che stai usando
(che qui mi sembra il POP).
Infatti se la rete è carica br.ready() darà false
e tu ti perdi il resto del messaggio.
Ad esempio succede con LIST dove il server molto probabilmente
farà tante write (una per ogni riga) e quindi tu ti leggi
solo la prima...
La tua condizione di uscita dai vari while
deve essere invece funzione del protocollo.
Per esempio con il POP3 le risposte a quasi tutte
le richieste (e sicuramente per la richiesta LIST)
terminano sempre con i 3 bytes . CR LF e quindi tu devi uscire
dai while solo quando leggi la sequenza di 3 bytes consecutivi
eguali a . CR LF
Infine un ultimo consiglio:
   se la br.ready() dice false allora fai una Thread.sleep
   per aspettare un secondo e non caricare inutilmente la tua macchina.
- Dario

 - Dario
Thank you very grazie :-)


 Bye
Ehm... io in effetti l'ho studiata sui doc java... dove posso approfondire?
Ciao,


 eguali a . CR LF
In verità la readLine() depura tutti i terminatori di riga 
("\r", "\n", "\r\n", dice la doc).  Quindi la condizione di uscita è
semplicemente: (line != ".")
Il ragionamento fila, io seguo la doc, e nonostante tutto non funzia:
persiste nel bloccarsi. Ok ammetto di essere io il folle. Guaritemi! :-)
Ecco la parte di prog modificata:
private static void list() throws Exception {
  String line = null;
  br = new BufferedReader(isr);
  // send
  System.out.print("LIST\n");
  os.write("LIST\n".getBytes());
  // receive
  do {
    line = br.readLine();
    System.out.println(line);
  } while (line != ".");
  // close: commentato perché la chiusura da problemi
  //br.close();
}
 


   } while (line != ".");
while (!line.equals("."));
Mannaia č un confronto fra stringhe. Inutile dire che adesso funzia tutto.
10 frustate prima di andare a letto sui chiodi.
Alx
