Question

Je construis une application client / serveur simple à l'aide de sockets java et j'expérimente avec ObjectOutputStream, etc.

J'ai suivi le didacticiel à cette adresse http: //java.sun .com / developer / technicalArticles / ALT / sockets commence à mi-chemin quand il est question de transporter des objets sur des sockets.

Voir mon code pour le client http: // pastebin. com / m37e4c577 Cependant, cela ne semble pas fonctionner et je ne peux pas comprendre ce qui ne fonctionne pas. Le code commenté en bas est directement copié du tutoriel - et cela fonctionne lorsque je viens de l'utiliser au lieu de créer l'objet client.

Est-ce que quelqu'un peut voir quelque chose que je fais mal?

Était-ce utile?

La solution

Le problème est l'ordre dans lequel vous créez les flux:

Dans le serveur de l'article (je suppose que c'est ce que vous utilisez), lorsqu'une nouvelle connexion est ouverte, le serveur ouvre d'abord un flux d'entrée, puis un flux de sortie:

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

L'exemple de code commenté utilise l'ordre inverse, établissant d'abord le flux de sortie, puis le flux d'entrée:

// 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());

Mais votre code le fait à l'inverse:

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

L’établissement d’une paire de flux de sortie / flux d’entrée sera bloqué jusqu’à ce qu’ils aient échangé leurs informations de prise de contact. Vous devez donc respecter l’ordre de création. Vous pouvez le faire simplement en remplaçant les lignes 34 et 35 de votre exemple de code.

Autres conseils

Vous n'écrivez l'objet nulle part.

Voir ce lien à nouveau, quelque part vous devez écrire:

 oos.writeObject( new Date() );

Dans votre code, vous avez seulement

ois.readObject();

C'est pourquoi

Juste un rappel.

Lorsque vous utilisez ObjectOutputStream, n'oubliez pas qu'il conserve un cache de références. Si vous écrivez un objet, modifiez le contenu de l'objet, puis renvoyez le même objet, vous obtiendrez des données en double. Par exemple:

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

Produira dans le côté client deux listes avec la chaîne "valeur1".

Pour éviter cela, la méthode de réinitialisation doit être appelée pour réinitialiser le cache de flux lors de l'écriture de la même référence d'objet à plusieurs reprises:

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

Vous aimerez probablement apprendre les bases les plus élémentaires en premier.

Voici un exemple que je viens de coder.

Il démarre un serveur , qui n'assiste qu'à UN client, puis envoie un objet et meurt.

Lorsque l'utilisateur (vous) appuyez sur Entrée, un nouveau client est créé, il se connecte au serveur créé précédemment et lit l'objet que le serveur enverra.

Aucune exception n'est gérée ici. Simplement pour simplifier les choses, mais ce n’est PAS la façon dont l’exception devrait être traitée.

Une fois que vous aurez compris tous les concepts, il sera plus facile de comprendre ceux du tutoriel.

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();

    }
}

J'espère que cela vous aidera.

Si vous aviez essayé un débogueur, il vous aurait dit où se trouvait le problème. (Peut-être pas pourquoi)

Le problème que vous avez est que ObjectOutputStream écrit un en-tête et ObjectInputStream lit cet en-tête. Vous avez d'abord créé ObjectInputStream, ce qui signifie qu'il tente de lire un en-tête qui ne sera jamais écrit.

Solution: créez toujours d'abord ObjectOutputStream et effacez-le () avant de créer ObjectInputStream.

Il est préférable d'ouvrir un outputStream car un flux de sortie ne bloque pas. Ensuite, vous avez le flux d'entrée qui attend un Stream . Après tous les flux, vous écrivez dans le flux et le vide - outputStream.flush () pour envoyer les octets de données. Vous aurez également besoin d’une méthode à l’autre extrémité pour lire l’entrée, qu’il s’agisse simplement de inputStream.read () , qui lit chaque octet sous forme d’entier pour un char , ou en utilisant un BufferedReader ou un Scanner . J'ai utilisé presque toutes les méthodes possibles, mais la méthode la plus efficace pour envoyer est outputStream.write (String) qui écrit une séquence de char sous forme de octet s dans le flux et la lecture de inputStream.read () lit un seul char . J'espère que cela aide.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top