Newsgroup: it.comp.java
Titolo: Selector, qualcuno lo ha già usato ?

Sto giocando con i Selector.
C'è una cosa che non mi piace nei risultati che ho ottenuto finora.
Dal lato del client il programma pare funzionare correttamente, ma
dal lato del server invece non mi piace.
Ho questo loop per gestire il Selector
0001     while (true) {
0002       int selezionati;
0003 
0004       try {
0005         selezionati = selettore.select();
0006       } catch (IOException ioe) {
0007         ioe.printStackTrace();
0008         break;
0009       } catch (ClosedSelectorException cse) {
0010         cse.printStackTrace();
0011         break;
0012       }
0013 
0014       System.out.print(".");
0015 
0016       if (selezionati > 0) {
0017         System.out.println("Selezionati: " + selezionati);
0018         Set pronti = selettore.selectedKeys();
0019 
0020         for (Iterator itrt = pronti.iterator(); itrt.hasNext();) {
0021           SelectionKey chiave;
0022           chiave = (SelectionKey)itrt.next();
0023           itrty.remove();
0024 
0025           if (chiave == echoKey) {
0026             ServerRunner svrr = new ServerRunner(echo.socket(), echoMsg);
0027             Thread thread = new Thread(svrr);
0028             thread.start();
0029 
0030           }
0031           else if (chiave == dataKey) {
0032             ServerRunner svrr = new ServerRunner(data.socket(), dataMsg);
0033             Thread thread = Thread(svrr);
0034             thread.start();
0035 
0036           }
0037           else {
0038             System.out.println("Selectedkey inattesa");
0039 
0040           }
0041 
0042 
0043         }
0044 
0045         pronti.clear();
0046 
0047 
0048       }
0049 
0050     }
(il  ServerRunner  non fa  altro  che  sparare sull'OutputStream  dell
ServerSocket il messaggio, come ho detto sto giocando. E' un Runnable
che ha un costruttore che accetta un ServerSocket su cui rispondere e
un messaggio da mandare al client)
Quello  che  succede  è  che  per  una  medesima  connessione  (telnet
localhost  porta)   il  selector  mi  ritorna  due   volte  la  stessa
SelectionKey, ambedue le volte con isAcceptable() che torna true.
Solo che la "seconda volta", quando faccio la accept sul ServerSocket
(che NON è nullo e nemmeno closed) mi arriva questa eccezione:
java.lang.NullPointerException
        at sun.nio.ch.ServerSocketAdaptor.accept(ServerSocketAdaptor.java:86)
        at MultiServer$ServerRunner.run(MultiServer.java:50)
        at java.lang.Thread.run(Thread.java:536)
Qualcuno ha  idea di  che test possa  fare sul ServerSocket  in questa
situazione  per evitarmi la  NullPointerException ?   (Troverei "diso-
norevole" il workaround della catch ...)
-- 
 /\            ___
/___/\__|_|\_|__|___Gian Uberto Lauri_____________________
  //--\ | | \|  |   Integralista GNUslamico  
\/		    e allevatore di bug da competizione

 norevole" il workaround della catch ...)
Mi sa che hai problemi di concorrenza... hai provato a spostare accept da
ServerRunner al blocco while che hai riportato sopra ovvero nel thread
principale (dopotutto non dovrebbe essere bloccante se hai fatto i compiti
giusti :-) ). Dimmi se funziona altrimenti specifica che sistema operativo
(domanda inutile dato che sei saint e quindi la risposta sarà linux) e che
versione di JVM.
Salumi.
        Claudio

> Sto giocando con i Selector.
CV> :-) non commento il codice dato che stai giocando: è il festival
CV> del thread che Selector dovrebbe invece minimizzare :-)))
1) ci sto giocando.
2) Serviva a  minimizzare i task (e  serve a minimizzare  i thread) in
listen (il Comer  me lo sono già studiato a suo  tempo). Io "gioco" al
servizio costoso (non  lo è, ma sto giocando e  quindi faccio finta lo
sia) e quindi  gli dedico un thread per essere  pronto a rispondere ad
una nuova  richiesta di  servizio. Se quel  servizio lo  avessi dovuto
mettere in produzione non avrei usato i thread.
CV> L'implementazione di questa classe sarebbe stata interessante dato
CV> che l'eccezione riportata riguarda proprio la classe ServerRunner.
Cosa c'è di interessante in una accept ? E *NEL* metodo accept che c'è
l'eccezione. 
CV> :-) ditto... sarebbe interessante avere la classe ServerRunner
CV> visibile :-)
Non ti servirebbe a nulla. Di codice eseguito c'è solo  la accept(). 
CV> Mi sa che hai problemi di concorrenza... hai provato a spostare
CV> accept da ServerRunner al blocco while che hai riportato sopra
CV> ovvero nel thread principale
OOOh, un buon suggerimento. Grassie.


>>>>> "CV" == Claudio Vesco <no...@chiedere.it.nospan> writes:
CV> Mi sa che hai problemi di concorrenza...
Ottima pensata, grazie e mille.   
Si  trattava proprio  di  questo.  Il  thread  principale rifaceva  la
select()  prima che  il thread  figlio avesse  possibilità di  fare la
accept() e quindi  il SelectableChannel non era cambiato  di stato nel
frattempo.
