Herramientas de usuario

Herramientas del sitio


bloque2:sockets

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

bloque2:sockets [2023/03/08 20:33] – [Método reset()] fernandobloque2:sockets [2024/09/16 20:53] (actual) – editor externo 127.0.0.1
Línea 390: Línea 390:
 . . . . . .
 public void recibirLista(){ public void recibirLista(){
-   ArrayList<Persona> listaRecibida = flujoEntrada.readObject();+   ArrayList<Persona> listaRecibida = (ArrayList<Persona>)flujoEntrada.readObject();
 } }
 </code> </code>
Línea 423: Línea 423:
 Cuando envío el mismo objeto repetidas veces a través del mismo extremo del socket, la clase ''ObjectOutputStream'' almacena en caché una copia de ese objeto, para que el envío sea más rápido la próxima vez. Cuando envío el mismo objeto repetidas veces a través del mismo extremo del socket, la clase ''ObjectOutputStream'' almacena en caché una copia de ese objeto, para que el envío sea más rápido la próxima vez.
  
-Esto genera el problema de que si yo modifico propiedades de ese objeto, la clase ''ObjectOutputStream'' no puede reconocer si el objeto ha modificado o es el mismo:+Esto genera el problema de que si yo modifico propiedades de ese objeto, el método ''writeObject()'' no puede reconocer si el objeto se ha modificado o es el mismo de antes, y envía la copia que tiene ya en caché de ese objeto:
  
 <code java> <code java>
Línea 432: Línea 432:
  
 persona.setNombre("Juan") persona.setNombre("Juan")
-salida.writeObject(persona); //Envía la copia almacenada en cache (sin modificar)+salida.writeObject(persona); //Envía la copia almacenada en cache (nombre->Fernando)
  
 persona.setNombre("Maria"); persona.setNombre("Maria");
-salida.writeObject(persona);  //Envía la copia almacenada en cache (sin modificar)+salida.writeObject(persona);  //Envía la copia almacenada en cache (nombre->Fernando)
 </code> </code>
  
-Cuando tengo una situación en la que debo enviar el mismo objeto modificado varias veces por un mismo canal, debo asegurarme de resetear la caché del flujo de salida ''salida.reset()'' después de enviar el objeto.+Cuando tengo una situación en la que debo enviar el mismo objeto modificado varias veces por un mismo canal, debo asegurarme de //resetear// la caché del flujo de salida (''salida.reset()''después de enviar el objeto.
  
 Esto puede ser algo necesario en una aplicación en la que envío varias veces un mismo  objeto ''List'' con una lista de objetos que se ha ido actualizando añadiendo o eliminando elementos. Esto puede ser algo necesario en una aplicación en la que envío varias veces un mismo  objeto ''List'' con una lista de objetos que se ha ido actualizando añadiendo o eliminando elementos.
Línea 444: Línea 444:
 En este caso, aparte de las clases para transmitir a través del socket, necesito leer desde un objeto //File// para enviarlo por el socket, y escribirlo en disco al recibirlo desde el otro lado del socket: Por lo tanto, necesito también las clases ''FileIn(Out)putStream''. En este caso, aparte de las clases para transmitir a través del socket, necesito leer desde un objeto //File// para enviarlo por el socket, y escribirlo en disco al recibirlo desde el otro lado del socket: Por lo tanto, necesito también las clases ''FileIn(Out)putStream''.
  
-  * Lado servidor:+  * Lado **emisor**abre y lee un fichero de origen y lo envía por el Socket.
 <code java> <code java>
-private Socket cliente;+private Socket socket;
 . . . . . .
 FileInputStream lectorFichero = new FileInputStream(fichero); FileInputStream lectorFichero = new FileInputStream(fichero);
-ObjectOutputStream salida = new ObjectOutputStream(cliente.getOutputStream());+ObjectOutputStream salida = new ObjectOutputStream(socket.getOutputStream());
        
-//Envío al cliente el tamaño total del fichero+//Envío al receptor el tamaño total del fichero
 salida.writeLong(fichero.length()); salida.writeLong(fichero.length());
              
Línea 465: Línea 465:
 </code> </code>
  
-  * Lado cliente:+  * Lado **receptor**abre un fichero de destino y escribe en él lo que lee desde el Socket.
 <code java> <code java>
 private Socket socket; private Socket socket;
Línea 472: Línea 472:
 ObjectInputStream entrada = new ObjectInputStream(socket.getInputStream()); ObjectInputStream entrada = new ObjectInputStream(socket.getInputStream());
        
-//Leo el tamaño del fichero que me ha enviado el servidor+//Leo el tamaño del fichero que me ha enviado el emisor
 long fileSize = entrada.readLong() long fileSize = entrada.readLong()
        
Línea 479: Línea 479:
 long totalLeido = 0; long totalLeido = 0;
 //El bucle debe terminar cuando ha recibido la totalidad de bytes //El bucle debe terminar cuando ha recibido la totalidad de bytes
-// Sin esa condición se va a quedar indefinidamente esperando a leer+// Sin esa condición, el bucle se va a quedar indefinidamente esperando a leer
 while( totalLeido < fileSize && (bytesLeidos = entrada.read(buffer)) > 0 ){ while( totalLeido < fileSize && (bytesLeidos = entrada.read(buffer)) > 0 ){
    escritorFichero.write(buffer, 0, bytesLeidos);    escritorFichero.write(buffer, 0, bytesLeidos);
-   totalLeido += bytesLeidos;+   totalLeido += bytesLeidos; //Llevo la cuenta de los bytes leidos
 } }
 escritorFichero.close(); escritorFichero.close();
 </code> </code>
  
 +Como acabamos de ver, para enviar un fichero, la parte del programa que lo envía a través del socket necesita enviarle previamente el tamaño de fichero para que el receptor sepa cuántos bytes debe leer. Si no enviamos el tamaño del fichero al receptor, el receptor nunca va a saber cuándo ha recibido la totalidad del fichero, y se quedará esperando a leer desde el socket indefinidamente.
  
 +Esto no ocurre con el flujo de lectura desde fichero, solamente con los flujos de lectura desde el socket. Cuando leemos desde un flujo de fichero (''FileInputStream''), hay un momento en que los bytes de ese fichero se acaban y el bucle se termina. Sin embargo al leer de un socket, no puedo saber cuándo se acaban los bytes ya que el socket seguirá abierto durante la ejecución de todo el programa, y puedo seguirlo usando para recibir otros ficheros más tarde.
 ==== Diferentes tipos de datos ==== ==== Diferentes tipos de datos ====
 Enviar objetos es útil, y lo podemos aplicar a la transferencia de ficheros. El cliente podría indicarle al servidor qué fichero desea descargar de una lista que previamente le envía el servidor. Enviar objetos es útil, y lo podemos aplicar a la transferencia de ficheros. El cliente podría indicarle al servidor qué fichero desea descargar de una lista que previamente le envía el servidor.
Línea 498: Línea 500:
 salida.writeObject(listaFicheros); salida.writeObject(listaFicheros);
 //Espera la selección del cliente //Espera la selección del cliente
-String seleccion = entrada.readObject();+String seleccion = (String)entrada.readObject();
  
 //Crea el fichero para enviar su tamaño y disponerse a enviarlo a través del socket //Crea el fichero para enviar su tamaño y disponerse a enviarlo a través del socket
Línea 510: Línea 512:
 <code java> <code java>
 //El cliente recibe la lista de ficheros disponibles al conectarse //El cliente recibe la lista de ficheros disponibles al conectarse
-List<String> listaFicheros = entrada.readObject();+List<String> listaFicheros = (List<String>)entrada.readObject();
 . . . . . .
 //Envía al servidor el String con la selección del usuario //Envía al servidor el String con la selección del usuario
bloque2/sockets.1678307628.txt.gz · Última modificación: 2024/09/16 20:53 (editor externo)