problema in invio di oggetti serializzabili utilizzando ObjectInputStream
-
28-09-2019 - |
Domanda
frammento dal codice del server:
public void run() {
try {
// Create data input and output streams
ObjectInputStream inputFromClient = new ObjectInputStream(
socket.getInputStream());
ObjectOutputStream outputToClient = new ObjectOutputStream(
socket.getOutputStream());
while (true) {
cop = inputFromClient.readObject();
String[][] m1=new String[][] {{"1", "1","1"}};
Object xx=new getSerialModel(m1);
outputToClient.reset();
outputToClient.writeObject(xx);
outputToClient.flush();
}
}
frammento da parte del Cliente:
//////////////
/// sockt jop
try {
// Create a socket to connect to the server
socket = new Socket("127.0.0."+Math.round(50+Math.random()*50), 8000);
// Create an output stream to send data to the server
toServer = new ObjectOutputStream(socket.getOutputStream());
toServer.flush();
}
catch (IOException ex) {
msgArea.append('\n' + ex.toString() + '\n');
}
///////////////////
//***
///////////////////
buttonSave.addActionListener(new ActionListener()
{ public void actionPerformed(ActionEvent ev)
{
System.out.println("Saving data is not implemented yet.");
String[][] m1={{"0","0","0"}};
for ( int i = 0 ; i < tableModel.getRowCount() ; i++ ){
{ for ( int j = 0 ; j < tableModel.getColumnCount() ; j++ )
m1[i][j]=(String)tableModel.getValueAt(i, j) ;
}
}
getSerialModel obt =new getSerialModel(m1);
try{
toServer.reset();
toServer.writeObject(obt);
toServer.flush();
}
catch (Exception ex) {
msgArea.append("cant reach the server its may be off" + '\n');
}
}
});
// button send msg
buttonsendtest.addActionListener(new ActionListener()
{ public void actionPerformed(ActionEvent ev)
{
try{
fromServer = new ObjectInputStream(socket.getInputStream());
Object mdata = fromServer.readObject();
tableModel.setDataVector((((getSerialModel)mdata).getmodel()), columnNames);
table.updateUI();
}
catch (Exception ex) {
System.out.print(ex.getStackTrace());
msgArea.append("cant reach the server its may be off "+ ex.toString() + '\n');
}
}
});
Quando provo a leggere oggetto serializzabile dai tempi multible del server, ottengo questa eccezione, per la prima volta il ricevitore lo lesse con successo.
java.io.StreamCorruptedException: invalid stream header: 00007571
come posso risolvere il problema?
Soluzione
Se si desidera creare più istanze ObjectInputStream in serie per lo stesso flusso di input presa, questa sembra una cattiva idea. Se il server sta scrivendo più oggetti allo stesso flusso di output, poi ci sono le informazioni relative serializzazione che solo viene inviato per oggetto unico, e solo la prima istanza ObjectInputStream sul client sarebbe in grado di leggere in modo affidabile questo. Utilizzando una sola istanza ObjectInputStream per flusso di ingresso presa e un'istanza ObjectOutputStream per flusso di uscita presa è probabilmente il più sicuro implementazione.
Inoltre, se si sta scrivendo più si oppone alla stesso ObjectOutputStream esempio sul lato server (cioè, writeObject multipla () le chiamate), questo può portare a intestazione del flusso problemi a causa di potenzialmente più riferimenti agli stessi oggetti (riferimenti in genere annidati) quando vengono letti dal flusso di input del cliente
Questo problema si verifica quando il flusso di uscita dell'oggetto avvolge un flusso di uscita della presa poiché durante la serializzazione normale, il secondo e successivi riferimenti a un oggetto non descrivono l'oggetto, ma utilizzano solo un riferimento. ObjectInputStream del cliente non ricostruisce gli oggetti correttamente per qualche motivo a causa di una differenza nelle informazioni di intestazione si aspetta (che non trattiene dal precedente readObject () le chiamate); questo sembra accadere solo con i flussi di socket, non file di I / O, ecc Questo problema non si verifica con la prima readObject chiamata (), ma piuttosto la seconda e quelle successive.
Se si desidera continuare a utilizzare lo stesso flusso presa di scrivere più oggetti, avrete bisogno di qualcosa di simile a quanto segue nel codice del server:
objectOut.reset()
objectOut.writeObject(foo);
Il reset () chiamata di ri-inizializza il torrente, ignorando lo stato di tutti gli oggetti precedentemente inviati lungo il torrente. Ciò assicura che ogni oggetto viene inviato nella sua interezza senza riferimenti manico tipo che vengono comunemente utilizzati per comprimere dati ObjectOutputStream ed evitare duplicazioni. E 'meno efficiente, ma ci dovrebbe essere alcuna corruzione dei dati quando viene letto dal client.
Altri suggerimenti
Dalla documentazione per ObjectInputStream .ReadObject () , cito:
Leggi un oggetto dalla ObjectInputStream. La classe della oggetto, la firma della classe, ei valori della non transitorio e campi non statici della classe e tutti i suoi supertipi vengono letti. deserializzazione predefinito per una classe può essere ignorato utilizzando la writeObject e metodi readObject. Oggetti di riferimento dall'oggetto vengono letti transitivamente in modo che un grafo equivalente completo oggetti vengono ricostruiti readObject.
Lo scopo principale è completamente ripristinata quando tutti i suoi campi e gli oggetti in esso riferimenti sono completamente ristrutturato. A questo punto il callback di convalida oggetto sono eseguiti in ordine in base alla loro priorità registrati. i callback sono registrati da oggetti (in readObject metodi speciali) in quanto sono individualmente restaurato.
Le eccezioni sono gettati per i problemi con l'InputStream e per le classi che non deve essere deserializzato. Tutti eccezioni sono fatali per la InputStream e lasciare in un stato indeterminato; spetta al chiamante di ignorare o recuperare il flusso Stato.
Specified by: readObject in interface ObjectInput Returns: the object read from the stream Throws: ClassNotFoundException - Class of a serialized object cannot be found. InvalidClassException - Something is wrong with a class used by serialization. StreamCorruptedException - Control information in the stream is inconsistent. OptionalDataException - Primitive data was found in the stream instead of objects. IOException - Any of the usual Input/Output related exceptions.
Direi che si sta cercando di leggere un oggetto prima che uno è stato scritto al flusso oggetto, o quella in cui il flusso di uscita non è stata lavata.
Si sta tentando di leggere in un oggetto di tipo 'Oggetto'. È così che è stato serializzato? È necessario assicurarsi che si sta leggendo l'oggetto nella stessa classe che è stato scritto da, ricorda quei fastidiosi serialVersionUID avvertimenti che vengono in su? Questa è la chiave per oggetto serializzazione e ricostruzione, da qui la necessità per le classi corrispondenti. Anche la ragione per cui è necessario aggiornare il vostro UID quando la struttura di classe modifiche.
Forse si sta cercando di leggere più volte lo stesso oggetto dal flusso, mentre il server ha scritto l'oggetto una sola volta.
In alternativa si sta cercando di utilizzare un ObjectInputStream prima di un corrispondente ObjectOutputStream è stato creato, e che invalida la comunicazione tra i due. Un ObjectOutputStream scrive un colpo di testa flusso di serializzazione al momento della sua creazione, e se non è creato prima il corrispondente ObjectOutputStream, che di testa si perde.