Ver Mensaje Individual
  #1 (permalink)  
Antiguo 12/03/2010, 19:02
MIRL27
Invitado
 
Mensajes: n/a
Puntos:
Sockets con ficheros grandes --> OutOfMemoryError

Hola

Estoy haciendo una aplicación cliente-servidor donde el cliente pide un fichero y el servidor lo envía, pero esos ficheros pueden llegar a pesar 1 o 2 GB.

El caso es que he probado con un fichero de menos de 600MB y cuando el cliente ya ha recibido 61MB el servidor da una excepción de OutOfMemoryError.

A ver si me podéis echar una mano, dejo parte del código con el que estoy probando:

Cliente:
Código:
public void pedir(String fichero) {
        try {
            // Crea la petición y la envía
            MensajeDameFichero mensaje = new MensajeDameFichero();
            mensaje.nombreFichero = fichero;
            out.writeObject(mensaje);
            /* Crea un stream de fichero donde almacenará los bytes que va recibiendo
            y consituirán el fichero recibido */
            ficheroRecibido = new FileOutputStream("a/"+mensaje.nombreFichero + EXTENSION);
            // Comienza a leer los bytes recibidos
            ObjectInputStream in = new ObjectInputStream(cliente.getInputStream());
            MensajeTomaFichero mensajeRecibido;
            Object mensajeAux;
            do {
                mensajeAux = in.readObject();
                if (mensajeAux instanceof MensajeTomaFichero) {
                    mensajeRecibido = (MensajeTomaFichero) mensajeAux;
                    ficheroRecibido.write(mensajeRecibido.contenidoFichero, 0, mensajeRecibido.bytesValidos);
                } else {
                    JOptionPane.showMessageDialog(null, "Error: Mensaje inesperado.", "Error", JOptionPane.ERROR_MESSAGE);
                    break;
                }
            } while (!mensajeRecibido.ultimoMensaje);
            in.close();
            close();
Servidor:
Código:
public void enviar(String fichero, ObjectOutputStream out) {
        try {
            boolean enviadoUltimo = false;
            // abre el fichero a enviar y configura las opciones de envío
            FileInputStream ficheroEnviar = new FileInputStream(fichero);
            MensajeTomaFichero mensaje = new MensajeTomaFichero();
            mensaje.nombreFichero = fichero;
            // empieza a leer y enviar el fichero
            System.out.println("Enviando "+fichero);
            int leidos = ficheroEnviar.read(mensaje.contenidoFichero);
            while (leidos > -1) {
                mensaje.bytesValidos = leidos;
                if (leidos < MensajeTomaFichero.LONGITUD_MAXIMA) {
                    mensaje.ultimoMensaje = true;
                    enviadoUltimo = true;
                } else {
                    mensaje.ultimoMensaje = false;
                }
                out.writeObject(mensaje);

                if (mensaje.ultimoMensaje) break;
                // Nuevo mensaje
                mensaje = new MensajeTomaFichero();
                mensaje.nombreFichero = fichero;
                leidos = ficheroEnviar.read(mensaje.contenidoFichero);
            }
            // si ha quedado el último paquete colgando --> lo envias
            if (!enviadoUltimo) {
                mensaje.ultimoMensaje = true;
                mensaje.bytesValidos = 0;
                out.writeObject(mensaje);
            }
            out.close();
            System.out.println("Enviado "+fichero);
        } catch (FileNotFoundException ex) {
            System.err.println("El fichero solicitado no existe.");
        } catch (IOException ex) {
            System.err.println("Excepción inesperada.\n"+ex);
        }
    }

He leído en la API que para ficheros mayores a 64K hay que indicar a ambos sockets (socket y serversocket) un tamaño mayor con setReceiveBufferSize(<tamaño>) para que cree los buffers del tamaño adecuado, pero aun indicándole un tamaño de 700MB (mi fichero es de menos de 600MB) sigue saltando la misma excepción.


Muchas gracias por adelantado.