Domanda

Sto costruendo una semplice applicazione client / server usando java socket e sperimentando ObjectOutputStream ecc.

Ho seguito il tutorial in questo URL http: //java.sun .com / developer / technicalArticles / ALT / sockets a metà strada quando si parla di trasporto di oggetti su socket.

Vedi il mio codice per il client http: // pastebin. com / m37e4c577 Tuttavia, questo non sembra funzionare e non riesco a capire cosa non funziona. Il codice commentato in fondo viene copiato direttamente dal tutorial - e funziona quando lo uso solo invece di creare l'oggetto client.

Qualcuno può vedere qualcosa che sto facendo di sbagliato?

È stato utile?

Soluzione

Il problema è l'ordine in cui si creano gli stream:

Nel server dell'articolo (che presumo sia quello che stai utilizzando), quando viene aperta una nuova connessione, il server apre prima un flusso di input, quindi un flusso di output:

public Connect(Socket clientSocket) {
 client = clientSocket;
 try {
  ois = new ObjectInputStream(client.getInputStream());
  oos = new ObjectOutputStream(client.getOutputStream());
 } catch(Exception e1) {
     // ...
 }
 this.start();
}

Il codice di esempio commentato utilizza l'ordine inverso, stabilendo prima il flusso di output, quindi il flusso di input:

// open a socket connection
socket = new Socket("localhost", 2000);
// open I/O streams for objects
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());

Ma il tuo codice fa il contrario:

server = new Socket(host, port);
in = new ObjectInputStream(server.getInputStream());
out = new ObjectOutputStream(server.getOutputStream());

L'instaurazione di una coppia di flussi di output / flussi di input si interromperà fino a quando non avranno scambiato le informazioni di handshaking, quindi è necessario abbinare l'ordine di creazione. Puoi farlo semplicemente scambiando le righe 34 e 35 nel tuo codice di esempio.

Altri suggerimenti

Non stai scrivendo l'oggetto da nessuna parte.

Vedi di nuovo quel link, da qualche parte devi scrivere:

 oos.writeObject( new Date() );

Nel tuo codice hai solo

ois.readObject();

Ecco perché

Solo un promemoria.

Quando si utilizza ObjectOutputStream, tenere presente che mantiene una cache di riferimento. Se si scrive un oggetto, si modifica il contenuto dell'oggetto e si invia nuovamente lo stesso oggetto, si otterranno dati duplicati. Ad esempio:

List list = new ArrayList();
list.add("value1");
out.writeObject(list);
list.clear();
list.add("value2");
out.writeObject(list);

Produrrà sul lato client due elenchi con la stringa "quot1 value".

Per evitare ciò, è necessario invocare il metodo di ripristino per ripristinare la cache del flusso quando si scrive più volte lo stesso riferimento oggetto:

List list = new ArrayList();
list.add("value1");
out.writeObject(list);
out.reset();
list.clear();
list.add("value2");
out.writeObject(list);

Probabilmente ti piacerebbe imparare prima i più elementari.

Ecco un esempio che ho appena codificato.

Avvia un server , che frequenta solo UN client e invia un oggetto e muore.

Quando l'utente (tu) premi invio, viene creato un nuovo client , si connette al server precedentemente creato e legge l'oggetto che il server invierà.

Nessuna eccezione viene gestita qui. Solo per semplificare le cose, ma NON è questo il modo in cui l'eccezione dovrebbe essere gestita.

Quando comprendi tutti i concetti qui, sarà più facile comprenderli nel tutorial.

import java.io.*;
import java.net.*;
import java.util.*;

public class SimpleServer implements Runnable { 

     // Creates the server, send a "date" and die.
    public void run() { 
        try {
            ServerSocket server = new ServerSocket( 8090 );
            Date creationDate = new Date();
            System.out.println("(Server) Server is ready " 
                                 + "and running at " + creationDate );

            Socket uniqueClient = server.accept();

            // We will write using this "chained" object.
            ObjectOutputStream out = new ObjectOutputStream( 
                                                 uniqueClient.getOutputStream());

            out.writeObject( creationDate );


            // close all, at this point forget about the exceptions.
            // this is lesson #1      
            out.close();

            uniqueClient.close();

            server.close();        

            System.out.println("(Server) The server is down");
        }catch( IOException ioe ) {}

     }

    public static void main ( String [] args ) throws IOException ,
                                                 ClassNotFoundException { 

         Thread serverThread = new Thread( new SimpleServer() );

         serverThread.start(); // start the server thread ... doh..

         System.out.println("(Client) Press enter when you want "+ 
                               " to connect to the server...");

         Scanner scanner = new Scanner( System.in );

         scanner.nextLine();

         Socket client = new Socket("localhost", 8090 );

         // Read from this object.
         ObjectInputStream in = new ObjectInputStream( client.getInputStream() );

         Date date = ( Date ) in.readObject();

         System.out.println("(Client) Current time is:          " + new Date() );
         System.out.println("(Client) Object read from server : " + date );

         in.close();
         client.close();

    }
}

Spero che questo aiuti.

Se avessi provato un debugger ti avrebbe detto dov'era il problema (forse non perché)

Il problema che hai è che ObjectOutputStream scrive un'intestazione e ObjectInputStream legge quell'intestazione. Prima hai creato ObjectInputStream, il che significa che sta cercando di leggere un'intestazione che non verrà mai scritta.

Soluzione: creare sempre prima ObjectOutputStream e scaricarlo () prima di creare ObjectInputStream.

È meglio aprire un outputStream perché un flusso di output non si blocca. Quindi, hai il flusso di input che attende un Stream . Dopo tutti gli stream, scrivi nello stream e svuotalo - outputStream.flush () per inviare i byte di dati. Avrai anche bisogno di un metodo all'altra estremità per leggere l'input, che si tratti semplicemente di inputStream.read () che legge ogni byte come numero intero per un char , oppure utilizzando un BufferedReader o Scanner . Ho usato quasi tutti i metodi possibili, ma il metodo più efficace per l'invio è outputStream.write (String) che scrive una sequenza di char come byte s nello stream e leggendo inputStream.read () si legge un singolo char . Spero che questo aiuti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top