Pregunta

Estoy creando una aplicación cliente / servidor simple usando sockets java y experimentando con ObjectOutputStream, etc.

He estado siguiendo el tutorial en esta url http: //java.sun .com / developer / technicalArticles / ALT / sockets comienza a mitad de camino cuando se habla de transportar objetos sobre sockets.

Vea mi código para el cliente http: // pastebin. com / m37e4c577 Sin embargo, esto no parece funcionar y no puedo entender lo que no funciona. El código comentado en la parte inferior se copia directamente del tutorial, y esto funciona cuando solo lo uso en lugar de crear el objeto cliente.

¿Alguien puede ver algo que estoy haciendo mal?

¿Fue útil?

Solución

El problema es el orden en que está creando las transmisiones:

En el servidor del artículo (que supongo es lo que está usando), cuando se abre una nueva conexión, el servidor abre primero una secuencia de entrada y luego una secuencia de salida:

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

El código de ejemplo comentado usa el orden inverso, primero establece la secuencia de salida, luego la secuencia de entrada:

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

Pero su código lo hace al revés:

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

El establecimiento de un par de flujo de salida / flujo de entrada se detendrá hasta que hayan intercambiado su información de comunicación, por lo que debe coincidir con el orden de creación. Puede hacerlo simplemente intercambiando las líneas 34 y 35 en su código de ejemplo.

Otros consejos

No estás escribiendo el objeto en ningún lado.

Vea ese enlace nuevamente, en algún lugar que tenga que escribir:

 oos.writeObject( new Date() );

En tu código solo tienes

ois.readObject();

Por eso

Solo un recordatorio.

Cuando use ObjectOutputStream, tenga en cuenta que mantiene un caché de referencia. Si escribe un objeto, cambia el contenido del objeto y luego envía el mismo objeto nuevamente, obtendrá datos duplicados. Por ejemplo:

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

Producirá en el lado del cliente dos listas con la cadena " value1 " ;.

Para evitar esto, se debe invocar el método de restablecimiento para restablecer la memoria caché de flujo al escribir la misma referencia de objeto varias veces:

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

Probablemente te gustaría aprender lo más básico primero.

Aquí hay una muestra que acabo de codificar.

Inicia un servidor , que atiende a UN solo cliente, y envía un objeto y muere.

Cuando el usuario (usted) presiona enter, se crea un nuevo cliente , se conecta al servidor creado previamente y lee el objeto que enviará el servidor.

No se maneja ninguna excepción aquí. Solo para simplificar las cosas, pero esta NO es la forma en que se debe manejar la excepción.

Cuando comprenda todos los conceptos aquí, será más fácil comprenderlos en el 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();

    }
}

Espero que esto ayude.

Si probaste un depurador, te habría dicho dónde estaba el problema. (Quizás no por qué)

El problema que tiene es que ObjectOutputStream escribe un encabezado y ObjectInputStream lee ese encabezado. Primero ha creado ObjectInputStream, lo que significa que está intentando leer un encabezado que nunca se escribirá.

Solución: Siempre cree primero el ObjectOutputStream y vacíelo () antes de crear el ObjectInputStream.

Es mejor abrir un outputStream porque una secuencia de salida no se bloquea. Luego, tiene la secuencia de entrada que espera una Stream . Después de todas las secuencias, usted escribe en la secuencia y la vacía - outputStream.flush () para enviar los bytes de datos. También necesitará un método en el otro extremo para leer la entrada, ya sea simplemente inputStream.read () que lee cada byte como un entero para un char , o utilizando un BufferedReader o Scanner . He usado casi todos los métodos posibles, pero el método más efectivo para enviar es outputStream.write (String) que escribe una secuencia de char s como byte s en la secuencia y leer inputStream.read () lee un solo char . Espero que esto ayude.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top