enviar un BufferedImage a travez de socket

Iniciado por egyware, 22 Agosto 2007, 22:55 PM

0 Miembros y 1 Visitante están viendo este tema.

egyware

ola estoy haciendo un programa (un casi troyano) que toma screenshoot del  server y los envia al client pero el problema es que no se como hacerlo y he buscado en google pero me he encontrado el mismo problema en otro idioma pero igual dejo un post aqui si alguien tiene una solucion mi problema es como un objeto BufferedImage lo paso a outputStream y lo paso por un socket y en el client de un inputStream a BufferedImage y pintarlo en pantalla
gracias de antemano
adiozzzz

Casidiablo

Lo primero a tener en cuenta es que para que un objeto pueda ser usado por sockets, es necesario que dicho objeto sea Serializable, es decir que implemente dicha clase. El problema es que la clase BufferedImage no implementa la interfaz Serializable.

De momento no se me ocurre nada, voy a echarle un vistazo a ver de que va la vaina.

Un saludo!

Yshua

yo ya eh hecho eso.
hay como en todo muchas formas.
una es crear un objeto de ImageIcon, q si es serializable,  y pasarlo por un socket con las clases ObjectInputStream y ObjectOutputStream, sin embargo, no recomiendo para nada este metodo pues cada imageIcon pesa unos 3 Mb, por lo q es demasiado lento.
otra forma entonces es convertir el BufferedImage a un byte[] eso se hace creando un objeto de ByteArrayOutputStream , y pasarlo como parametro al metodo estatico ImageIO.write()(este metodo tiene mas parametros) luego que escribiste la imagen en el ByteArrayOutputStream esta clase tiene un metodo toByteArray y retorna un byte[], luego ese byte[] lo envias f{acilmente por sockets. es algo como eso. esa si la recomiendo. cada imagen, dependiendo de la resolucion estara entre los 50 y los 200 Kb.
no explico como hacerlo explicitamente por q no lo recuerdo exacto en este momento. pero puedes mirar como hacerlo.

Baruj aba beshem Adonai.
<a href="http://www.cp666group.com">visita mi sitio CP666GROUP</a>

Casidiablo

Inspirado en las bonitas palabras de Yshua, he intentado lo que dice y el resultado es el siguiente:

Clase Receptor.java: Se queda a la espera/escucha de conexiones en determinado puerto y recibe una imagen. En este caso he guardado la imagen en un archivo, pero las posibilidades son muchas:
Código (java) [Seleccionar]
import java.io.*;
import java.net.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
public class Receptor{
    private ObjectInputStream entrada;
    private ServerSocket servidor;
    private Socket conexion;
    public void ejecutarServidor() {
        try {
            servidor = new ServerSocket( 12345, 100 );
            while ( true ) {
                try {
                    esperarConexion();
                    entrada = new ObjectInputStream( conexion.getInputStream() );
                    System.out.println( "\nSe recibieron los flujos de entrada\n" );
                    procesarConexion();
                } catch ( EOFException excepcionEOF ) {
                    System.err.println( "El servidor terminó la conexión" );
                    excepcionEOF.printStackTrace();
                } finally {
                    cerrarConexion();   // Paso 5: cerrar la conexión.
                }
            } // fin de instrucción while
        } // fin del bloque try
        catch ( IOException excepcionES ) {
            excepcionES.printStackTrace();
        }
       
    } // fin del método ejecutarServidor
    // esperar que la conexión llegue, después mostrar información de la conexión
    private void esperarConexion() throws IOException {
        System.out.println( "Esperando una conexión\n" );
        conexion = servidor.accept(); // permitir al servidor aceptar la conexión
        System.out.println( "Conexión recibida de: " + conexion.getInetAddress().getHostName() );
    }
    // procesar la conexión con el cliente
    private void procesarConexion() throws IOException {
        do { // procesar los mensajes enviados por el cliente
           
            // leer el mensaje y mostrarlo en pantalla
            try {
                byte[] bytesImagen = (byte[]) entrada.readObject();
                ByteArrayInputStream entradaImagen = new ByteArrayInputStream(bytesImagen);
                BufferedImage bufferedImage = ImageIO.read(entradaImagen);
               
                String nombreFichero=System.getProperty("user.home")+File.separatorChar+"captura.jpg";
                System.out.println("Generando el fichero: "+nombreFichero );
                FileOutputStream out = new FileOutputStream(nombreFichero);
                // esbribe la imagen a fichero
                ImageIO.write(bufferedImage, "jpg", out);
            }
           
            // atrapar problemas que pueden ocurrir al tratar de leer del cliente
            catch ( ClassNotFoundException excepcionClaseNoEncontrada ) {
                System.out.println( "\nSe recibió un tipo de objeto desconocido" );
            }
           
        } while ( true );
       
    } // fin del método procesarConexion
    // cerrar flujos y socket
    private void cerrarConexion() {
        System.out.println( "\nFinalizando la conexión\n" );
        try {
            entrada.close();
            conexion.close();
        } catch( IOException excepcionES ) {
            excepcionES.printStackTrace();
        }
    }
    public static void main( String args[] ) {
        Receptor aplicacion = new Receptor();
        aplicacion.ejecutarServidor();
    }
}


Clase Cliente.java: Ésta clase toma una captura de la pantalla, y luego envía dicha imágen como un arreglo de bytes al servidor especificado.
Código (java) [Seleccionar]
import java.io.*;
import java.net.*;
import javax.imageio.ImageIO;
import java.io.Serializable;
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
public class Cliente{
    private ObjectOutputStream salida;
    private String servidorChat;
    private Socket cliente;
   
    public Cliente( String host ) {
        servidorChat = host; // establecer el servidor al que se va a conectar este cliente
    }
    private void ejecutarCliente() {
        try {
            conectarAServidor(); // Paso 1: crear un socket para realizar la conexión
            salida = new ObjectOutputStream( cliente.getOutputStream() );
            salida.flush(); // vacíar búfer de salida para enviar información de encabezado
            System.out.println( "\nSe recibieron los flujos de E/S\n" );
            enviarDatos();
        } catch ( EOFException excepcionEOF ) {
            System.err.println( "El cliente termino la conexión" );
        }
       
        // procesar los problemas que pueden ocurrir al comunicarse con el servidor
        catch ( IOException excepcionES ) {
            excepcionES.printStackTrace();
        }
       
        finally {
            cerrarConexion(); // Paso 4: cerrar la conexión
        }
       
    } // fin del método ejecutarCliente
   
    // conectarse al servidor
    private void conectarAServidor() throws IOException {
        System.out.println( "Intentando realizar conexión\n" );
        // crear Socket para realizar la conexión con el servidor
        cliente = new Socket( InetAddress.getByName( servidorChat ), 12345 );
        // mostrar la información de la conexión
        System.out.println( "Conectado a: " +
                cliente.getInetAddress().getHostName() );
    }
    // cerrar flujos y socket
    private void cerrarConexion() {
        System.out.println( "\nCerrando conexión" );
        try {
            salida.close();
            cliente.close();
        } catch( IOException excepcionES ) {
            excepcionES.printStackTrace();
        }
    }
    private void enviarDatos( ) {
        Rectangle rectangleTam = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
        try {
            Robot robot = new Robot();
            BufferedImage bufferedImage = robot.createScreenCapture(rectangleTam);
            ByteArrayOutputStream salidaImagen = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "jpg", salidaImagen);
            byte[] bytesImagen = salidaImagen.toByteArray();
            salida.writeObject( bytesImagen );
            salida.flush();
            System.out.println( "Se ha enviado la imagen" );
        } catch (AWTException e) {
            e.printStackTrace();
        } // procesar los problemas que pueden ocurrir al enviar el objeto
        catch ( IOException excepcionES ) {
            System.out.println( "\nError al escribir el objeto" );
        }
    }
   
    public static void main( String args[] ) {
        Cliente aplicacion;
       
        if ( args.length == 0 )
            aplicacion = new Cliente( "127.0.0.1" );
        else
            aplicacion = new Cliente( args[ 0 ] );
       
        aplicacion.ejecutarCliente();
    }
   
} // fin de la clase Cliente


El programa funciona!!! Pero... me sale una excepción que no he sabido depurar:

java.io.EOFException
        at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
        at java.io.ObjectInputStream.readObject0(Unknown Source)
        at java.io.ObjectInputStream.readObject(Unknown Source)
        at Receptor.procesarConexion(Receptor.java:43)
        at Receptor.ejecutarServidor(Receptor.java:17)
        at Receptor.main(Receptor.java:74)


Eso sucede después de que la imágen ya ha sido creada, y el problema es que la imágen no queda bien al 100% o algo raro pasa, es decir, puedes ver la imagen con el Gimp o Paint (que comparación tan burda XD), pero con el visor de imágenes de Windows no.

Y pues no sé como solucionar el problema :-\

Yshua

que bien q te haya sido de ayuda, lo q escribí.
para lo de la excepcion trata cerrando el flujo out. no se no se me ocurre nada más.

Baruj aba beshem Adonai.
<a href="http://www.cp666group.com">visita mi sitio CP666GROUP</a>

egyware

#5
gracias por la ayuda, ayer estuve como a las 4 de la  mañana(-4 GMT) tratando de enviar el bufferedImage mejor dicho recibirlo porque lo enviava pero no lo podia recibir y incluso invente un metodo pero no funciono (guardarlo en el disco y enviar ese archivo) cuando llege a mi casa(ubicada en la punta del cerro literalmente) pruebo el codigo que me dejaron (analizarlo pero no copiarlo jamas!!) gracias por su ayuda  ;) :P :o



PD: Estado anilizando el codigo (aun no lo he probado) si BufferedImage no es serialiable aqui tu lo haces serializable  (:o que fantastico) hoy trabajare en eso si es que tengo tiempo gracias.
EOF = end of file eso significa cierto tendra algo que ver con el problema tendre que verlo
PD:Disculpame CasiDiablo no pude revisar tu codigo pero tengo uno mejor
es algo asi envias el BufferedImage a traves de ImageIO.write(image,"jpg",OutputStream) ese OutputStream es del socket
y en el cliente si resiviste informacion  anterior para que el metodo no te haga reset uno llama al metodo InputStream.markSuport() y recibe la imagen conImageIO.read(InputStream) pero hay un problema se queda pegado en esa sentencia a menos que cierre el server

passatempo

Reviviendo este post, la imagen no la puedes abrir por que falto un

out.close();

después de 

ImageIO.write(bufferedImage, "jpg", out);

en la parte del receptor.
Agregenlo y asi queda finalizada la imagen.
BTW excelente programa  ;-)