PDA

Visualizza la versione completa : [Java] problemi con la classe Socket


tonytalk
19-01-2003, 14:03
Ringrazio in anticipo tutti coloro che mi potranno dare qualunque tipo di suggerimento,ho un problema inerente alla classe

socket o almeno credo.

In poche parole, ho creato un sito in cui si pu giocare a risiko online, il server fila liscio per un bel p di ore, ma

ad un certo punto si blocca tutto e non riceve pi messaggi dai client.

Ora ho notato che dopo 10 di minuti si riprende e prima di riprendersi mi lancia questa eccezione:


ScambiaMessaggi.run() IOException...Run() user=NOMEGIOCATORE eccezione=java.net.SocketException: Connection timed out:

Connection timed out
java.net.SocketException: Connection timed out: Connection timed out
at java.net.SocketInputStream.socketRead(Native Method)
at java.net.SocketInputStream.read(SocketInputStream. java:86)
at java.net.SocketInputStream.read(SocketInputStream. java:102)
at java.io.DataInputStream.readInt(DataInputStream.ja va:338)
at Server.ScambiaMessaggi.run(ScambiaMessaggi.java:31 )


l'istruzione a ScambiaMessaggi.java:31 la seguente
int i = _inputStream.readInt();

e _imputStream stata inizializzata nel costruttore della classe che riceve come paramentro il socket con la seguente

istruzione
_inputStream = new DataInputStream(_socket.getInputStream());


Inoltre,il blocco del server non immediato ma avviene piano piano. Inizialmente pensavo fosse un errore di deadlock ma

posso assicurarvi che non lo .
Se non sbaglio, il blocco dei thread avviene sulla classe che invia a tutti i client un messaggio...non so dirvi se il

blocco avviene quando invia il messaggio al client che in seguito mi d poi l'eccezione di timeout

Ora io penso che il problema dipenda dal socket e soprattutto vorrei capire in quale circostanza viene lanciata

l'eccezione sul time out mi potrebbero servire i metodi (anche se non so a cosa servono) socket.setSoTimeout()?


Aggiungo infine che, leggendo con il metodo socket.getSOTimeout() mi ritorna il valore 0.

Grazie ancora

blinkago
19-01-2003, 14:28
C' qualche problema di disconnessione...
Qualche client esce senza chiudere il socket..

penso!

tonytalk
19-01-2003, 14:34
Grazie blinkago
In genere le disconnessioni anomale, le rimuovo con una classe Ping.
Il mio Ping invia un messaggio ogni 5 minuti e si accorge se un utente disconnesso al secondo Ping quindi se tutto va male...
occorrono quasi 15 minuti per disconnetterlo.

Cmq se fosse come tu dici, allora mi sa che il problema non dipende da questa eccezione.

Volevo inoltre chiederti se devo utilizzare il metodo Socket.setSOTimeout(milliseconds) e impostare un tempo maggiore di 15 minuti per evitare questa eccezione?

blinkago
19-01-2003, 22:41
in teoria dovresti far usare dal client socket.close() per terminare il tutto in modo corrretto!!
Se fai gi cos, dovresti rivedere l'implementazione del server in modo da far terminare il tutto in modo corretto!!

tonytalk
20-01-2003, 18:37
In teoria, quando un utente si scollega o con il ping mi accorgo che cascato io chiudo il socket.

Forse il ping che male che vada ci impiega quasi 15 minuti e troppo rispetto al time out del socket???

Sta di fatto che questa eccezione viene sollevata una o due massimo 3 volte al giorno e prima di questa eccezione il server incomincia ad andare in crash ...via via non invia messaggi a nessuno e dopo il lancio di questa eccezione ricomincia tutto a funzionare

HELPPPPPPPPPPPPPPPPPPP

:confused: :confused: :confused:

lelefante
20-01-2003, 18:52
Cosi' alla cieca non e' possibile aiutarti, a meno che uno non abbia gia' avuto il tuo stesso problema. Quello che ti consiglio e' di trovare la parte del codice in cui avviene l'errore, fare un bloco try catch e gestire le eccezioni nell' ordine: TimeOut, Socket e IO, in modo da capire esattamente quale e' il problema.
Da quanto mi pare di capire il problema avviene nel server che attende in lettura un dato da un client. Cerca di stabilire quale e' il client che va in errore (cioe' quello da cui il server si aspetta il messaggio che non arriva) e se possibile fai una tabella in cui registri i tempi in cui i client spediscono dei messaggi.
Un'idea che mi viene in mente e' che un client va in timeout perche' passa troppo tempo da quando spedisce un messaggio a un altro, magari perche' i tempi degli altri giocatori si sono accumulati.

Quante piu' informazioni riesci a reperire, tanto piu' e' possibile darti una mano. :)

tonytalk
20-01-2003, 19:05
Allora l'eccezione dal lato server, viene lanciata dal Thread collegato con il socket al client, l'unico motivo...per il quale penso possa bloccare tutti gli altri aiutanti sta nel fatto che utilizzo anche una classe con un metodo sincronizzato (Send.SendAll(message)) e questo utente in un modo da me inspiegabile blocca il socket e quindi blocca la classe synchorized e via via blocca gli altri utenti.

Quando viene lanciata questa eccezione, il server butta via il thread e molto probabilmente libera la classe con il metodo synchronized

Ora io non capisco ...dal file log del server io vedo arrivare messaggi da questo utente...ad un certo punto non mi arriva niente poi dopo qualche minuto (4-5-6 minuti) incominciano a bloccarsi gli utenti dopo 14-15-16 minuti viene lanciata questa eccezione

Scusami...forse non sar stato chiaro ma devo chiudere la connessione

Ciao a tutti e grazie per tutti i consigli



SendAll

lelefante
20-01-2003, 23:55
Ok, cerca di stabilire altre informazioni: nelle eccezioni dei Socket ci sono dei metodi di "diagnostica", posta i vari messaggi.
PrintStackTrace, getCause, getMessage e getLocalizedMessage.
Inoltre cerca di stabilire se e' sempre lo stesso utente a mandare tutto in time out, controlla i tempi di risposta del ping... come al solito piu' inforamzioni riesci a recuperare, meglio e'.

Una cosa, ma se tu quando gestisci l'eccezione chiudi il socket dell'utente in time out, poi non riesci a proseguire normalmente con il gioco?
E poi, nel client, vengono lanciate delle eccezioni? In questo caso si potrebbe pensare a un modo per non far cadere il tutto (anche se stilisticamente fa un po' schifo, almento riesci a tenere in piedi il gioco).

tonytalk
21-01-2003, 13:55
Lo stack stato scritto nel primo post, non sempre lo stesso utente a generare l'eccezione e per quanto riguarda il client non ti so dare informazioni, in quanto non sono mai riuscito a simulare il blocco e quindi non ho potuto avere info.

Poi ti dico cosa altro ho scoperto...


Dopo un silenzio di circa 10 minuti del client XXXX segue l'eccezione sul time-out dell'utente XXXX e un'altra eccezione nella classe Send di XXXX(la classe sinchronized che viene usata per l'invio di un messaggio, ora non so dirti qual' il Thread che lancia l'eccezione nell'oggetto send di XXXX, cmq questa info l'avr entro domani.

Ti spiego come gestito il socket
Quando un utente si collega instanzio un oggetto sulla classe Aiutante che estende Thread con un ciclo infinito nel metodo run

Questa classe ha due oggetti uno una istanza della classe Send e un altro la condivisione della classe SendAll(che contiente tutti gli oggetti Send)

Quando il client invia un messaggio, parte il thread che era fermo sul imputstream nel metodo run() e esegue le operazioni del messaggio e quindi andra poi nella classe Send ad inviare qualcosa.

Le due eccezioni che ricevo...vengono date la prima (time-out)nella classe Aiutante (quindi quella che sta ricevendo) e subito dopo nella classe Send (quella che sta inviando)

Da qui in poi ...ho un bel p di eccezioni sempre sull'oggetto send XXXXX e poi il server riparte quindi sblocca tutti.


Grazie ancora per il sostegno morale ma sto veramente scoppiando su questo problema :dh: :dh: :dh: :dh:


PS : se volete provare il blocco del server...andate al mio sito, vi fate una partitina a risiko...se si dovesse bloccare non scollegatevi..attendete una decina di minuti ...e tutto rifunzioner

tonytalk
22-01-2003, 15:46
Ogni giocatore sul server ha un oggetto
class synchronized send

e inoltre ogni giocatore condivide un oggetto sendAll che in pratica un hashtable che contiene tutti oggetti send

Il server incomincia ad andare in palla quando un giocatore XXXXXsta inviando un messaggio a YYYYY e resta bloccato su tale classe, dopo poster il codice del metodo invia() della classe send

via via che altri giocatori inviano messaggi a tutto il gruppo o ad un sottogruppo, restano giustamente bloccati sull'oggetto sincronizzato send del giocatore =YYYYY(se questo fa parte del gruppo) e attendono la fine di XXXXXche avverr dopo una decina di minuti in seguito al lancio di questa eccezione.

ScambiaMessaggi.run() IOException...Run() user=YYYYY eccezione=java.net.SocketException: Connection timed out: Connection timed out
java.net.SocketException: Connection timed out: Connection timed out
at java.net.SocketInputStream.socketRead(Native Method)
at java.net.SocketInputStream.read(SocketInputStream. java:86)
at java.net.SocketInputStream.read(SocketInputStream. java:102)
at java.io.DataInputStream.readInt(DataInputStream.ja va:339)
at Server.ScambiaMessaggi.run(ScambiaMessaggi.java:36 )
Esco da ScambiaMessaggi.run user==YYYYY


E subito dopo segue l'eccezione di XXXXX


Send_Synchroinized.send() IOException...invio messaggi all' user==YYYYY eccezione=java.io.IOException: Broken pipe
Thread che ha provocato l'eccezione Thread[XXXXX,5,main]
java.io.IOException: Broken pipe
at java.net.SocketOutputStream.socketWrite(Native Method)
at java.net.SocketOutputStream.write(SocketOutputStre am.java:62)
at java.io.DataOutputStream.writeByte(DataOutputStrea m.java:134)
at Server.Send_Synchronized.invia(Send_Synchronized.j ava:39)
at Server.Partite.SendAllGames(Partite.java:286)
at Server.StatoMappa.SendAggiornaTerr(StatoMappa.java :153)
at Server.Partite.SendAggiornaTerr(Partite.java:172)
at Server.Aiutante.PiazzaArmate(Aiutante.java:1498)
at Server.Aiutante.parseMessage(Aiutante.java:183)
at Server.ScambiaMessaggi.run(ScambiaMessaggi.java:58 )

Quindi tutto si sbloccato e incominciano ad arrivare tutti i messaggi

---->MESSAGGIO ARRIVATO AL SERVER->nuovo messaggio<- GESTISCE L'UTENTE ZZZZZ

ecc...

ecco il metodo invia

public synchronized boolean invia(MyMessage mymessage){
if(_outputStream == null) return false;

try{
int i = mymessage.size();
_outputStream.writeInt(i);

for(int j = 0; j < i; j++){
byte byte0 = mymessage.getType(j);
_outputStream.writeByte(byte0);

if(byte0 == 0){
_outputStream.writeInt(mymessage.getInt(j));
}else{
byte abyte0[] = mymessage.getBuffer(j);
_outputStream.writeInt(abyte0.length);
_outputStream.write(abyte0, 0, abyte0.length);
}//Fine IF
}//Fine For
_outputStream.flush();
}catch(IOException ioexception){
System.out.println("Send_Synchroinized.send() IOException...invio messaggi dall' user="+user+" eccezione="+ioexception.toString());
System.out.println("Thread che ha provocato l'eccezione "+Thread.currentThread().toString());
ioexception.printStackTrace(System.out);
eccezioneIO=true;
return false;

}catch(Exception exception){
System.out.println("Send_Synchroinized.send() ECCEZIONE...invio messaggi dall' user="+user+" eccezione="+exception.toString());
exception.printStackTrace(System.out);
return false;
}
return true;
}

La seconda eccezione data quando invoco un write, non sempre lo stesso

Grazie a tutti spero che qualcuno mi possa dare una mano per risolvere questo problema

PS Scambiamessaggi la classe che riceve i messaggi in imput sul server di un giocatore

Loading