View Full Version : [JAVA]java.io.StreamCorruptedException
Questo pezzo di codice:
while(connesso){
try{
ObjectInputStream is=new ObjectInputStream(cs.getInputStream());
Dati in=(Dati)is.readObject();
catch(Exception e){
System.out.println("Client disconnesso");
connesso=false;
}
}
Mi solleva l'eccezzione di cui sopra, di cosa si tratta? Com'è possibile che i dati si danneggiano?
In particolare ho questa eccezzione quando ci sono almeno 3 client connessi e non subito ma dopo un po' di tempo(casuala) che restano connessi.
La connessione è di questo tipo:
client A client B e server S
A deve comunicare con B:
A invia i dati ad S, S li invia a B ma anche ad A,A legge i dati , B legge i dati.
Idem per B.
Up nessuna sa niente? devo postare più codice?
sottovento
15-07-2006, 16:03
cs e' una socket? Leggi un solo dato? Per leggere questo dato crei ogni volta un ObjectInputStream? Lo sai che ObjectInputStream aggiunge delle informazioni a quanto spedisci, in modo da ricostruire correttamente l'oggetto in arrivo? Lo sai che questo ti obbliga a scrivere mediante il corrispondente ObjectOutputStream?
Quando scrivi, apri e chiudi Object stream alla stessa maniera? Lo sai che quando apri uno stream di questo tipo vengono subito spediti dei dati in maniera "trasparente" all'operatore?
Scusa la serie di domande. Probabilmente la soluzione e' nelle risposte di quest'ultime (spero)
High Flying
Sottovento
Ciao, siccome non riesco bene a capire quello che mi hai chiesto comunque cs è il socket del client, creato così: cs=ss.accept();
ss è il ServerSocket .
Comunque dal codice che ho incollato si vede che creo ongi volta un objectinputstream, il quale legge un solo tipo di dato, ma li legge di continuo perchè il server li invia di continuo.
sottovento
17-07-2006, 10:06
Ciao, siccome non riesco bene a capire quello che mi hai chiesto comunque cs è il socket del client, creato così: cs=ss.accept();
ss è il ServerSocket .
Comunque dal codice che ho incollato si vede che creo ongi volta un objectinputstream, il quale legge un solo tipo di dato, ma li legge di continuo perchè il server li invia di continuo.
Scusa, non sono stato chiaro.
Le domande che avevo posto erano per cercare di individuare il problema:
- ogni volta apri un object input stream. Questo si aspetta di trovare alcuni dati (che java inserisce in modo "trasparente" a te) all'interno dello stream.
Va da se che devi trattare la spedizione nella maniera speculare, i.e. aprire un object output stream tutte le volte e spedire l'oggetto.
- non puoi aprire lo stream una volta all'apertura della socket?
- Non ho visto la chiusura dello stream
L'idea che mi sono fatto e' che ci sia "disparita'" fra il codice che spedisce e quello che riceve: se, per esempio, spedisci dei semplici byte, non potrai riceverli con un ObjectInputStream, perche' Java manca delle informazioni per restituirti l'oggetto del tipo giusto (castato poi a Object).
Fai una verifica, e posta poi qualche info
High Flying
Sottovento
Ciao, non ho chiuso lo stream perchè altrimenti mi sollevva un eccezzione, di tipo socket is closed... non so perchè però.
Comunque quel codice è l'invio dati da parte di un client, che li invia di continuo, dall'alktra parte c'è il server che rimane sempre in ascolta dei dati, il tipo di dato che invio è sempre e solo uno quindi non c'è il problema della possibile diversità del dato inviato.
sottovento
17-07-2006, 10:18
Ciao, non ho chiuso lo stream perchè altrimenti mi sollevva un eccezzione, di tipo socket is closed... non so perchè però.
Comunque quel codice è l'invio dati da parte di un client, che li invia di continuo, dall'alktra parte c'è il server che rimane sempre in ascolta dei dati, il tipo di dato che invio è sempre e solo uno quindi non c'è il problema della possibile diversità del dato inviato.
Ciao,
grazie per le info. Purtroppo non abbiamo ancora chiarito come vengono spedite quelle informazioni. Le spedisci tramite un ObjectOutputStream costruito sopra la socket?
L'eccezione di socket closed fa pensare che probabilmente non chiudevi l'ObjectInputStream ma la socket stessa.
Se vuoi, pubblica un pezzo di codice in piu' sia per il client sia per il server. Fra un po' vado a cena e poi lo provo
High Flying
Sottovento
Ti ringrazio per l'interssamento! Certo che ti posto del codice ecco qua, questo è come il server spedisce l'oggetto:
public void scrivi(Dati out){
try{
ObjectOutputStream os=new ObjectOutputStream(cs.getOutputStream());
os.writeObject(out);
//server.aggiornaLog("\nOUT-"+out.getNick()+" size="+cs.getSendBufferSize());
os.flush();
}
catch(Exception e){
server.aggiornaLog("\nErrore "+e+" da parte di "+dato.getNick());
}
}
se chiudo l'ObjectOutputStream dopo aver spedito l'oggetto mi da sempre errore, come se chiudessi il socket!
Come vedi scrivo lo stesso tipo di dato(Dati).
Il problema forse potrebbe essere causato da un altro pezzo di codice.
Ti spiego, questo server resta sempre in ascolto dai client(ogni client ha il suo thread) e quando arriva un dato da un client il server(usando il codice qui sopra) lo invia a tutti i client che lo ricevano usando il codice postato al primo post.
Potrebbe essere la causa dell'errore? Nota comunque che non posso chiudere nessun sttream perchè mi da sempre l'eccezzione socketclosed.
Se mi connetto con un solo client va tutto benone, con due client gira parecchio tempo ma poi a volte da streamCorrupted, con tre client quasi subito da errore...
sottovento
17-07-2006, 15:53
Ciao,
la procedura scrivi() e' quindi chiamata per ogni client connesso. Ovviamente passerai la socket in qualche modo, immagino che non scriverai sempre sulla stessa.
Perdonami ma sono sempre convinto che aprire una ObjectXXputStream ogni volta non sia una buona tecnica, overhead a parte. Ti e' possibile modificare in modo da aprire una volta sola? Ti risolverebbe anche il problema di dover chiudere, visto che hai l'eccezione di socket closed...
Cmq il fatto di avere una trasmissione a piu' client NON ti dovrebbe dare alcun problema. Ovviamente ogni client ha la propria socket aperta verso il server, giusto? (Scusa se faccio tante domande, e' per chiarire....).
Una curiosita': come fai a passare le varie socket su cui scrivere? Aggiorni un membro della classe?
Se hai un vettore di socket o se hai un thread per socket non dovrebbe essere difficile aprire la ObjectXXputStream una sola volta...
High Flying
Sottovento
Vediamo se con questa spiegazione mi riesco a far capire meglio.
Ho un server, il quale resta in ascolto su una determinata porta della richiesta di connessione da parte dei client, quando un client si connette, il server crea il socket per il client(socketClient=socketServer.accept();) e fa partire un thread dedicato solo per quel client passandogli il socketClient.
In questo modo il server dedica un thread per ogni client per comunicare.
Il server si salva anche tutti i riferimenti ai thread creati per ogni client in una lista, in modo da poter inviare i dati ai client dall'esterno(cioè da fuori il thread).
Sono riuscito come da te suggerito a fare in modo di aprire gli stream solo una volta, in pratica alla creazione dei thread dedicati creo anche gli stream sui socket interessati.
Il fatto è che ora sembra non funzionare nulla, cioè non vi sono eccezzioni sollevate, ma il server ed i client non comunicano...
sottovento
17-07-2006, 16:28
Scusa, questo era chiaro. La selva di domande e' per cercare l'errore.
Se vuoi (o se puoi), pubblica il codice. E' davvero strano, DEVE andare. L'architettura che hai descritto e' "pulita", non ci sono scuse, deve andare per forza!
Se ti invio tutto ci daresti un'occhiata? però non è commentato...
Tanto si tratta di una prova, tutto il codice è fine a se stesso, solo per provare questo tipo di comunicazione.
sottovento
17-07-2006, 16:32
Ok. Qui e' notte fonda, do un'occhiata e vado a dormire. Casomai rispondo domani.
High Flying
Sottovento
Ecco qui (http://allejp.altervista.org/classes.rar)
La main class è Main.class (che fantasia eh :D )
Ti ringrazio aspetto una tua risposta!
sottovento
17-07-2006, 16:41
Ecco qui (http://allejp.altervista.org/classes.rar)
La main class è Main.class (che fantasia eh :D )
Ti ringrazio aspetto una tua risposta!
:confused: Non vedo nessun allegato... e' il mio browser o una semplice dimenticanza?
se clicchi su "qui" non ti scarica nulla?
cmq per sicurezza http://allejp.altervista.org/classes.rar
forse con firefox non fa scaricare direttamente, in tal caso usa explorer!
sottovento
17-07-2006, 17:01
se clicchi su "qui" non ti scarica nulla?
cmq per sicurezza http://allejp.altervista.org/classes.rar
forse con firefox non fa scaricare direttamente, in tal caso usa explorer!
Roger. Ora l'ho preso, ma... contiene i .class!
Riprovo domattina.
High Flying
Sottovento
Che stupido che sono si mi sn dimenticato i .java :doh:
Rimedio intanto, buonanotte!
Ecco qui ci sono i file java... scusa ancora.
http://www.easy-sharing.com/570027/src.rar.html
sottovento
18-07-2006, 08:03
Buongiorno,
prima di tutto, complimenti: scrivi il codice in maniera chiara e pulita. Non e' da tutti.
Ho dato un'occhiata, ed ho fatto delle piccole modifiche, mettendo dei commenti (in inglese). Le modifiche le ho marcate con DW (downwind, sottovento in inglese), di cui molte sono semplicemente per debug (dei messaggi a video).
Ho aperto una sola volta gli stream, ho fatto girare l'applicazione con un paio di client e li ho lasciati aperti tutta la mattina (circa 4 ore). Ogni tanto li controllavo, battevo un paio di tasti e tornavo a fare dell'altro.
Sembra che non appaia piu' il corrupted stream. Spero che tu possa provarlo in maniera piu' seria di quanto ha fatto il sottoscritto ed eventualmente mi faccia sapere.
Fra le modifiche: oltre a quella di aprire un object stream nel costruttore, ho evitato di creare un thread all'interno di un thread. non conosco l'applicazione (magari ti serve) ma per il codice che mi hai spedito mi sembrava ridondante.
IMPORTANTE: facendo le prove, mi sono ricordato di un problema - l'object input stream resta bloccato fintanto che non si apre, dall'altra parte, un object output stream!
Quindi, quando crei gli stream, devi stare attento a creare prima l'output e poi l'input, altrimenti la tua applicazione e' bloccata.
Spero di esserti stato di aiuto, e spero di vedere la tua applicazione girare.
High Flying
Sottovento
Buondì!
Guarda, non so come ringraziarti per l'interessamente che hai avuto, grazie mille!
L'apertura degli stream l'hai messa dove l'avevo messa io quando giustamente mi hai consigliato di aprirli solo una volta(però non avevo fatto caso al fatto di aprire prima l'output), solo che come ti avevo riferita sembrava che client e server non comuicassero.
Ecco, anche ora ho lo stesso problema utilizzando il tuo codice, ma ciò mi porta a pensare che allora sia un problema mio e solo mio visto che da te funziona!
Cosa potrebbe essere? Non ci sono eccezzioni in giro ma non comunicano!
ps.grazie per i complimenti sul codice mi fanno davvero piacere! :D
sottovento
18-07-2006, 08:31
Beh, non erano complimenti, era una analisi di quanto ho visto.
Purtroppo nel mio lavoro devo mettere le mani nel codice altrui, quindi parlo con cognizione di causa. Scrivi del buon codice.
Tornando al problema: ho semplicemente battuto dei tasti e controllato che stesse tutto in piedi.
Ho notato anche (mediante delle scritte di debug) che il server continua ad inviare dei dati ai client. Non ho potuto approfondire (sono al lavoro), ma mi sembrava strano.
Quanto dici ora mi fa pensare che forse non era proprio quello che volevi. Col tuo permesso, stasera controllo ancora.
Nel frattempo, se hai nuove versioni, tienimi aggiornato
High Flying
Sottovento
Si il server manda in continuazione i dati ai client, questo è dovuto al fatto che i client mandando continuamente al server i dati sulla loro posizione, ed il server appena riceve qualcosa reinvia tutto ai client, quindi è un ciclo infinito, il client spedisce al server e per risposta il server rispedisce al client.
Anche con un solo client connesso si nota questo perchè il client per sapere la propria posizione deve spedirla al server, il server la rispedisce al client che la può elaborare(disegna la pallina).
Comunque certo che ti tengo aggiornato, ora sto lavorando anche su una versione che usa l'UDP, sto cercando di fare qualcosa di simile ai più comuni giochi in commercio, ossia che quando si avvia l'applicazione si interroga un server primario il quale contiene la lista di tutti i server creati, così che si possa scegliere un server dalla lista e connettersi.
Ogni server creato però resta connesso direttamente (TCP) al server primario in modo da granatire la priopria "presenza".
Ora purtroppo devo preaparare un esame di fisica eh non posso lavorarci molto...
Visto che sei al lavoro non posso che dirti buon lavoro!
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.