Visualizzazione dei risultati da 1 a 9 su 9
  1. #1

    classe Selector con SocketChannel in OPWRITE

    Salve,
    stavo facendo qualche prova per vedere come funziona la classe Selector e SocketChannel per quanto riguardava la classio NIO.

    Ho fatto un programma che crea due Thread. Un Thread server che accetta una connessione e inizia a leggere.
    L'altro Thread crea uno socketchannel e un selector impostando il controllo sullo stato di scrittura. Ossia mi deve avvertire quando nel canale io posso scrivere.

    SocketChannel canale=SocketChannel.open(new InetSocketAddress("localhost",12345));
    canale.configureBlocking(false); // non bloccante
    Selector selezione=Selector.open(); // creo il selector
    canale.register(selezione,SelectionKey.OP_WRITE); // metto il controllo sullo stato di scrittura


    Subito, appena connesso, faccio una selector per vedere se posso scrivere nel canale. Correttamente, mi dice che ci posso scrivere sul canale perchè il buffer è vuoto.

    Subito dopo aver fatto la Selector a fare le seguenti cose:
    scrivere nel buffer e fare la selector
    controllare nuovamente subito la selector.

    In entrambi i casi dopo la prima selector, la seconda chiamata non seleziona alcun canale. Ritorna cioè che su ZERO canali posso farci le operazioni che volevo fare, cioè in questo caso significa che l'unico canale creato non posso scriverci! Eppure non ci ho fatto alcuna operazione ancora.

    Le specifiche del selector dicono:
    This method performs a blocking selection operation. It returns only after at least one channel is selected, this selector's wakeup method is invoked, or the current thread is interrupted, whichever comes first.
    Appena chiamo la select esce selezionando zero canali. A questo punto mi chiedo qualche è l'errore!


    Questo è il codice del client incriminato:
    codice:
                Thread.sleep(1000);
                SocketChannel canale=SocketChannel.open(new InetSocketAddress("localhost",12345));
                canale.configureBlocking(false);
                Selector selezione=Selector.open(); //Creo il selector
                canale.register(selezione,SelectionKey.OP_WRITE); // Registro per la scrittura
                byte stringa[]=new byte[1000]; // Creo un buffer
                System.out.println("Client: Riempio il buffer di merda");
                for(int m=0; m<stringa.length;m++) stringa[m]=(byte)((m*65537)%253-126);
                System.out.println("Stringa creata");
                ByteBuffer buffer = ByteBuffer.wrap(stringa);
                int i=0;
                int num=selezione.select(); // Provo a fare la select
                if(num>0) { // La prima chiamata ha sempre successo
                    Set vari=selezione.keys();
                    Iterator vario=vari.iterator();
                    while(vario.hasNext()) {
                        SelectionKey abla=(SelectionKey)vario.next();
                        System.out.println("Questo socket è in scrittura") // Questo lo stampa;
                    }
                }
                System.out.println("Trovati "+num+" channel pronti"); // Stampa che ha trovato un canale
                num=selezione.select(); // Riprovo a fare la select
                if(num>0) { 
                    Set vari=selezione.keys();
                    Iterator vario=vari.iterator();
                    while(vario.hasNext()) {
                        SelectionKey abla=(SelectionKey)vario.next();
                        System.out.println("Questo socket è in scrittura?");
                    }
                }
                System.out.println("Trovati "+num+" channel pronti"); // Questa volta nessun canale è pronto
                System.out.println("Sto spedendo sul canale "+canale);
                System.out.flush();
                int scritti=canale.write(buffer); // scrivo nel buffer
    
                System.out.println("Spedito tutto ("+scritti+") \nClient in attesa della select");
                System.out.println( "Processed "+buffer.limit()+" from " );
                num=0;
                while(num==0) {  // il ciclo si ripete saturando uno dei core del processore
                    num=selezione.select(); // faccio la select non bloccante
                    System.out.println("Trovati "+num+" channel pronti. Connesso:"+selezione); // Stampa che ha trovato zero canali pronti
                    
                }
                System.out.println("Client: esco"); // Non arriva mai a questo punto.

    E' tre giorni che non capisco qualche è l'errore. Lo so che è la prima volta che programmo in java, ma non pensavo fosse così traumatico iniziare ;_;

    Vi prego, help me!

    grazie in anticipo
    ...

  2. #2
    Utente di HTML.it L'avatar di @DI3GO@
    Registrato dal
    Nov 2008
    Messaggi
    537

    Re: classe Selector con SocketChannel in OPWRITE

    Originariamente inviato da LordSaga640

    E' tre giorni che non capisco qualche è l'errore. Lo so che è la prima volta che programmo in java, ma non pensavo fosse così traumatico iniziare ;_;
    Scusa ma non ci credo...hai parecchia teoria alle spalle, anche perchè ho letto l'altro post dove consigliavi un Threadpool, cmq...
    Ma se non ho capito male un selector controlla il canale?

    Quello che ti posso consigliare è di leggere attentamente la sessione di selection, infatti ( leggendo molto rapidamente e mi prendo la resp. di eventuali cazz... scritte di seguito ) pare che se tra una select e l'altra non ci sono state operazioni che hanno "compromesso" la gestione delle keys ( le collection set ), queste non vengono aggiornate come tutte libere, ma come una non variazione della situazione di prima....però temo di aver letto molto male....e sopprattutto sono stanco, ma credo che al 99% la strada da seguire sia quella dello studio dei passi della selection...QUI
    Nipote: persona incompetente, con le soli doti di "copia/incolla" e la creazione automatica di siti internet ed interfaccie grafiche.Compie lavori apparentemente qualificati e richiesta una modifica sparisce in quatemala con i pochi soldi ottenuti.[...] Fonte la Diegonzelli

  3. #3

    Re: Re: classe Selector con SocketChannel in OPWRITE

    Originariamente inviato da @DI3GO@
    Scusa ma non ci credo...hai parecchia teoria alle spalle, anche perchè ho letto l'altro post dove consigliavi un Threadpool, cmq...
    Ma se non ho capito male un selector controlla il canale?

    Quello che ti posso consigliare è di leggere attentamente la sessione di selection, infatti ( leggendo molto rapidamente e mi prendo la resp. di eventuali cazz... scritte di seguito ) pare che se tra una select e l'altra non ci sono state operazioni che hanno "compromesso" la gestione delle keys ( le collection set ), queste non vengono aggiornate come tutte libere, ma come una non variazione della situazione di prima....però temo di aver letto molto male....e sopprattutto sono stanco, ma credo che al 99% la strada da seguire sia quella dello studio dei passi della selection...QUI
    Ciao, intanto grazie della risposta!

    Lo script che sto facendo è solo un esperimento, delle prove per vedere come lavorare con il selector in java. Devo realizzare una piattaforma che include tra le altre cose un client di bit torrent con il KAD e il client di bit torrent è la parte più facile di questa piattaforma... vabbè, uno inizia...anche se non finisce l'opera però si impara a programmare decentemente in questo linguaggio di programmazione.

    Come puoi capire non posso creare un thread per ogni connessione.
    Posso però creare un thread che si occupa di gestire tutte le connessione, in entrata e in uscita e quelle pendenti.

    Ho controllato meglio la documentazione ma non sembra che ci siano problemi. Ho provato a fare il flush dello stream. Ho provato ad inviare dati piccoli e grandi quantità di dati per vedere se lo stato cambiava...ho provato a riimpostare il selector... ma nada.
    Io penso a questo punto che sia un problema correlato in qualche modo a questo bug:
    http://bugs.sun.com/bugdatabase/view...bug_id=4755720

    Guarda caso anche questo tizio usa win 2k, e da quello che so è un sistema operativo simile a windows xp x64 (che è quello che ho io).

    Il fatto che la Selector.select() dovrebbe sbloccarsi solo quando uno dei canali è pronto per l'operazione che stai richiendo. Esce anche se non ci sono le operazioni richieste SOLO quando riceve una interruzione da un altro Thread. Basta solo questo per farmi pensare ad un bugs.
    Insomma, alla fine il mio progettino non può neanche partire per via di un bugs del java ;_;


    Mi puoi eseguire questo codice?
    codice:
    package provevarie;
    import java.net.*;
    import java.nio.channels.*;
    import java.nio.*;
    import java.util.*;
    
    public class Main {
    
    
        public Main() {
            new pippo().start();
            System.out.println("Avvio Thread Client");
            try {
                Thread.sleep(1000);
                SocketChannel canale=SocketChannel.open(new InetSocketAddress("localhost",12345));
                canale.socket().getOutputStream().flush();
                canale.configureBlocking(false);
                Selector selezione=Selector.open();
                canale.register(selezione,SelectionKey.OP_WRITE);
                byte stringa[]=new byte[1000];
                System.out.println("Client: Riempio il buffer di merda");
                for(int m=0; m<stringa.length;m++) stringa[m]=(byte)((m*65537)%253-126);
                System.out.println("Stringa creata");
                ByteBuffer buffer = ByteBuffer.wrap(stringa);
                int i=0;
                int num=selezione.select();
                if(num>0) {
                    Set vari=selezione.keys();
                    Iterator vario=vari.iterator();
                    while(vario.hasNext()) {
                        SelectionKey abla=(SelectionKey)vario.next();
                        if( (abla.interestOps() & SelectionKey.OP_WRITE)== SelectionKey.OP_WRITE) {
                            System.out.println("E' impostato su WRITE!");
                        }
                        abla.interestOps(SelectionKey.OP_WRITE);
                        System.out.println("Questo socket è in scrittura?");
                    }
                }
                System.out.println("Trovati "+num+" channel pronti");
               
                num=selezione.select();
                if(num>0) {
                    Set vari=selezione.keys();
                    Iterator vario=vari.iterator();
                    while(vario.hasNext()) {
                        SelectionKey abla=(SelectionKey)vario.next();
                        System.out.println("Questo socket è in scrittura?");
                    }
                }
                System.out.println("Trovati "+num+" channel pronti");
                System.out.println("Sto spedendo "+canale);
                System.out.flush();
                int scritti=canale.write(buffer);
    
                System.out.println("Spedito tutto ("+scritti+") \nClient in attesa della select");
                System.out.println( "Processed "+buffer.limit()+" from " );
                num=0;
                while(num==0) { 
                    num=selezione.select();
                       canale.register(selezione, SelectionKey.OP_WRITE);
                    if(num>0) System.out.println("Ti funziona la selection!!! Ti invidio.");
                    Thread.sleep(1500);
                }
                System.out.println("Client: esco");
                return;
               
            } catch (Exception e) {
                 System.out.println("Errore Client " +e+" "+e.getMessage()+" ");
                return;
            }
            
        }
        public static void main(String[] args) {
                new Main();
        }
    
    }
    class pippo extends Thread {
        
        @Override
        public void run() {
            System.out.println("Avvio Thread server");
            ServerSocketChannel questa;
            ServerSocket qst;
            SocketChannel connessione;
            SocketChannel canale;
            try {
                questa=ServerSocketChannel.open();
                qst = questa.socket();
                InetSocketAddress isa = new InetSocketAddress( 12345 );
                 qst.bind( isa );
                System.out.println("Sever Creato socket.");
        
                connessione=questa.accept();
                System.out.println("Server accettata la richiesta.");
                ByteBuffer tmp=ByteBuffer.allocate(100000);
                while(connessione.isConnected()) {
                    tmp.clear();
                    int letti=connessione.read(tmp);
                   System.out.println("Letto ben "+letti+" "+tmp.toString()+" "+tmp.array()[0]);
                }
                System.out.println("Connessione terminata. CChiusura del Thread");
            } catch(Exception e) {
                System.out.println("Errore Server " +e+" "+e.getMessage()+" "+e.getStackTrace());
            }
            
            
        }
    }
    Se ti compare questa scritta dopo 5 secondi circa allora ti funziona sul tuo SO:
    Ti funziona la selection!!! Ti invidio.

    Grazie mille, scusa il disturbo e grazie dell'aiuto!
    ...

  4. #4
    Il java mi piace sempre meno!
    ....
    http://bugs.sun.com/bugdatabase/view...bug_id=4469394

    Non-blocking SocketChannels registered with a Selector and including the
    SelectionKey.OP_WRITE operation code will not release Selector.select() more
    than once
    .
    Però il problema si riferisce al 2001! Possibile che sia sempre lo stesso?


    EDIT:
    io per scrupolo ho segnalato il bug alla sun. Vediamo ora cosa dicono. Se ho sbagliato io avrò fatto la figura del fesso. Però la soluzione la voglio XD
    ...

  5. #5
    Utente di HTML.it L'avatar di @DI3GO@
    Registrato dal
    Nov 2008
    Messaggi
    537
    Ma nel bug viene anche dichiarato
    Release Fixed1.4.2 ( mantis )
    Semmai prova ad eseguire il codice di verifica del bug che è riportato sotto, almeno puoi stare certo che si tratti di quello.
    Cmq il codice che mi hai postato lo provo stasera.
    Nipote: persona incompetente, con le soli doti di "copia/incolla" e la creazione automatica di siti internet ed interfaccie grafiche.Compie lavori apparentemente qualificati e richiesta una modifica sparisce in quatemala con i pochi soldi ottenuti.[...] Fonte la Diegonzelli

  6. #6
    Utente di HTML.it L'avatar di @DI3GO@
    Registrato dal
    Nov 2008
    Messaggi
    537
    Ho provato a lanciare il tutto, ma si blocca pure a me...
    Appena avrò un attimo di tempo proverà a guardare il codice in dettaglio per cercare di capire quale possa essere il problema...Se tu hai trovato una soluzione fammi sapere, perchè interessa anche a me.
    Nipote: persona incompetente, con le soli doti di "copia/incolla" e la creazione automatica di siti internet ed interfaccie grafiche.Compie lavori apparentemente qualificati e richiesta una modifica sparisce in quatemala con i pochi soldi ottenuti.[...] Fonte la Diegonzelli

  7. #7
    Utente di HTML.it L'avatar di @DI3GO@
    Registrato dal
    Nov 2008
    Messaggi
    537
    STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
    1. Run the enclosed source code in DOS box.
    2. From DOS, run "telnet localhost 10064"
    3. The source will issue of unending "write at **ticks**"
    4. run the code with java nio_test reset to unregister OP_WRITE

    EXPECTED VERSUS ACTUAL BEHAVIOR :
    I would expect that I get one isWritable keys until I
    actually write something.

    REPRODUCIBILITY :
    This bug can be reproduced always.

    ---------- BEGIN SOURCE ----------
    import java.nio.channels.*;
    import java.net.*;
    import java.util.*;

    public class nio_test
    {
    public static void main(String[] args) throws Exception
    {
    System.out.println("Java Version: " + System.getProperty
    ("java.vm.version", "???"));

    boolean reset = (args.length > 0);

    Selector selector = Selector.open();
    ServerSocketChannel server = ServerSocketChannel.open();
    server.configureBlocking(false);
    InetSocketAddress address = new InetSocketAddress(10064);
    server.socket().bind(address);
    server.register(selector, SelectionKey.OP_ACCEPT);
    SocketChannel socket = null;

    for(;
    {
    if ( selector.select() > 0 )
    {
    Set keys = selector.selectedKeys();
    Iterator iterator = keys.iterator();
    while ( iterator.hasNext() )
    {
    SelectionKey key = (SelectionKey)iterator.next();
    iterator.remove();

    if ( key.isAcceptable() )
    {
    System.out.println("accept at " + System.currentTimeMillis());

    socket = server.accept();
    socket.configureBlocking(false);
    socket.socket().setTcpNoDelay(false);
    socket.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
    }
    else
    {
    if ( key.isWritable() )
    {
    System.out.println("write at " + System.currentTimeMillis());
    if (socket != null && reset) {
    socket.register(selector, SelectionKey.OP_READ);
    }
    }
    else if ( key.isReadable() )
    {
    System.out.println("read at " + System.currentTimeMillis());
    }
    }
    }
    }
    }
    }
    }

    ---------- END SOURCE ----------

    CUSTOMER WORKAROUND :
    Don't use OP_WRITE
    (Review ID: 163452)
    ================================================== ====================
    Questo è il codice di esempioo fornito dalla Sun, testato e funzionante, quindi decisamente non c'è nessun bug, ma viene istanziato qualcosa in modo errato.
    Ora devo scappare, ma appena ho 5 minuti di tempo spero riuscirò a dirti anche cosa!
    Nipote: persona incompetente, con le soli doti di "copia/incolla" e la creazione automatica di siti internet ed interfaccie grafiche.Compie lavori apparentemente qualificati e richiesta una modifica sparisce in quatemala con i pochi soldi ottenuti.[...] Fonte la Diegonzelli

  8. #8
    Si funziona.

    Dopo qualche milione di test. Ho scoperto che nell'iterator, subito dopo il next() bisogna fare remove(). Se non si fa il select() impazzisce.

    La sun mi ha detto che risolveranno presto questo problema che afflige le java.nio

    Hi Daniele Guiducci,

    Thank you for reporting this issue.

    We have determined that this report is a new bug and entered the bug into our internal bug tracking system under Bug Id: 6776558.
    Strano che nessuno si fosse reso conto di questo bug...vabbè....
    cmq svelato l'arcano. Sto aspettando che mi sistemino la libreria così posso continuare.
    Tra qualche giorno il bug sarà pubblico. Dovrebbe essere inserito tra i veri high priority.

    Notte^^
    ...

  9. #9
    Utente di HTML.it L'avatar di @DI3GO@
    Registrato dal
    Nov 2008
    Messaggi
    537
    Originariamente inviato da LordSaga640
    Si funziona.

    Dopo qualche milione di test. Ho scoperto che nell'iterator, subito dopo il next() bisogna fare remove(). Se non si fa il select() impazzisce.

    La sun mi ha detto che risolveranno presto questo problema che afflige le java.nio



    Strano che nessuno si fosse reso conto di questo bug...vabbè....
    cmq svelato l'arcano. Sto aspettando che mi sistemino la libreria così posso continuare.
    Tra qualche giorno il bug sarà pubblico. Dovrebbe essere inserito tra i veri high priority.

    Notte^^
    VVoVe: Ah....Beh....Sembra strano....Quindi c'è un passaggio obbligatorio che è la remove....secondo me la risolveranno chiamando quel metodo alla successiva richiesta della select....è anche logico fare così!
    Nipote: persona incompetente, con le soli doti di "copia/incolla" e la creazione automatica di siti internet ed interfaccie grafiche.Compie lavori apparentemente qualificati e richiesta una modifica sparisce in quatemala con i pochi soldi ottenuti.[...] Fonte la Diegonzelli

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.