PDA

Visualizza la versione completa : Chat con Java


morpheus81
19-01-2003, 19:33
salve
sono alle prime armi con java.net, sto cercando di creare un server che f comunicare vari Telnet come una chat, il problema che non so come poter ricevere e inviare contemporaneamente messaggi.
Mi spiego il programma server, crea due buffer associati ad un socket, uno in entrata e uno in uscita, il problema che il server in attesa che qualcosa arrivi dal buffer e non pu introdurre niente nel buffer di uscit afinch il client non gli invia niente.
Insomma la chat sincrona,finch uno non scrive l'altro non puo' farlo.
Non mi rispondete semplicemente usa i Thread, perch ci provato, quindi magari se questa era la strada giusta vi ringrazierei se mi deste qualche dritta in piu'.


grazie

lelefante
19-01-2003, 20:35
Non mi rispondete semplicemente usa i Thread, perch ci provato, quindi magari se questa era la strada giusta vi ringrazierei se mi deste qualche dritta in piu'.

Direi che ti sei risposto da solo :gren:
A parte gli scherzi una soluzione semplice puo' essere questa:
Crea un oggetto MainServer che rimane in ascolto su di una porta, in attesa che dei client vi si connettano.
Ogni volta che un client si connette il MainServer crea un oggetto socket per poter dialogare con il client: il problema (che tu stesso hai riscontrato) e' che se il server si mette a comunicare con quel client chiunque altri provi a connettersi troverebbe la porta occupata.
Per evitare questo quando il MainServer crea il socket lo passa poi ad un altro oggetto che si incarica di utilizzarlo.
Es:


class MainServer implements Runnable {
private int thePort;
private ServerSocket theSocket;
private boolean done=false;
private Thread theThread;

MainServer( int port) {
thePort = port;
}

public void run() {
//esce se il metodo viene chiamato dall'esterno
if(Thread.currentThread != theThread) return;
while(!done) {
try {
//il metodo accept() restituisce un socket associato
//al client appena connessosi
new ConnManager( theSocket.accept());
} catch(IOException eIO) {}
}
}

//l'unico modo per far partire il MainServer
//e' chiamare start()
public void start()
throws IOException
{
theSocket = new ServerSocket(thePort);
theThread = new Thread(this).start;
}

//Per buona creanza ricordarsi di chiamare stop()
public void stop() {
done = true;
if(theThread != null && theThread.isAlive())
theThread.interrupt();
try {
theSocket.close();
} catch(IOExcpetion eIO) {}
}
}

In questo stralcio, come vedi, il MainServer non fa altro che attendere nuovi client, per passarli ad un altro oggetto, di tipo ConnManager, il quale si preoccupera' di dialogare con il client secondo un protocollo che stabilisci tu.

Chiaramente questa soluzione e' mooolto grezza, ma lascia spazio ad ampi margini di miglioramento, a seconda di quello di cui hai bisogno.
Buon lavoro. :)

morpheus81
19-01-2003, 20:49
Grazie molte mi metto subito al lavoro.

ciao

morpheus81
19-01-2003, 21:08
Per leggendo bene il tuo listato, forse non mi sono spiegato, infatti il mio reale problema non che ci sono piu' client.
Mettiamo che ci sia un solo client, il fatto che se il server ha un buffer in attesa di dati (in questo caso stringhe), come pu un utente che vuole scrivere un messaggio dal server che arrivi al client ?? (infatti l'OUT non pu essere inviato se il server ha il buffer in attesa in entrata).

grazie

morpheus81
19-01-2003, 21:11
Per farti capire ancora meglio:
anche se lancio due thread, uno che si occupa dell'invio e uno della ricezione, essi non funzioneranno mai insieme e quindi il tutto non funziona come una chat che io posso inviarti anche due stringhe una dopo l'altra prima che tu mi risponda.
ciao

blinkago
19-01-2003, 22:50
A me coi thread funziona tutto a meraviglia!!
Rivedi il tuo progetto!
Avrai fatto qualche erore concettuale...

lelefante
20-01-2003, 23:41
Ho capito qual e' il tuo problema. La soluzione e' fare interagire i due thread con un semaforo.
Potresti strutturare la cosa in questo modo:
un thread e' quello del server, che si occupa di ricevere i messaggi dai client, che poi deve ridistribuire (quindi non mi riferisco a quello che riceve le connessioni, qui non ne tengo conto).
Questo thread rimane in attesa su un semaforo: fino a che questo e' disattivato il thread rimane in stato di wait.
Il client, invece, e' composto da 2 thread: uno che rimane in ascolto sul socket per vedere se un utente ha spedito un messaggio, l'altro rimane anch'esso in attesa su un semaforo.
Quando un utente invia un messaggio, il thread del client incaricato della ricezione lo memorizza. A quel punto passa il messaggio al server, attiva il semaforo (sempre del server) e sveglia il thread. Poi si rimette in ascolto sulla porta, in attesa di altri messaggi.
Il thread del server, una volta uscito dallo stato di wait, si accorge del semaforo attivo, lo disattiva di nuovo e va a leggere il messaggio. Quindi si occupa di reindirizzarlo a tutti i client (tranne, ovviamente, a quello che l'ha spedito).
Per spedire il messaggio ai client compie le stesse operazioni di prima: invia il messaggio ai client (mi riferisco ai client risiedenti sulla macchina "server", scusa il gioco di parole, non a quelli remoti degli utenti), attiva il semaforo del thread in attesa e poi lo sveglia.
Il client, a quel punto, si trova con due thread attivi: uno che continua ad attendere i messaggi, e l'altro che finalmente ha qualcosa da fare: spedire al client remoto il messaggio (dopo aver disattivato il semaforo, ovviamente).

Come soluzione mi sembra la piu' accettabile: in termini di prestazioni un thread in stato di wait non consuma cicli macchina, semmai e' oneroso in termini di memoria... e' un compromesso da vagliare. Devi un po' darti da fare per quanto riguarda la sincronizzazione dei thread, ma come idea credo che funzioni.

morpheus81
21-01-2003, 00:40
Hai centrato il punto, ti ringrazio per la tua articolatissima risposta, si penso che sia il caso di fare come dici te.
Proprio una bella pensata.
ciao

pippo75
21-01-2003, 09:02
hai provato anche a dare un'occhio al progetto jxta (http://www.jxta.org/)?
un progetto per il p2p in java, dovrebbe funzionare anche dietro proxy e firewall


mandi :)

Loading