Resultados 1 al 10 de 10

Tema: Problema al leer de un socket

  1. #1 Problema al leer de un socket 
    Iniciado
    Fecha de ingreso
    Feb 2012
    Mensajes
    4
    Descargas
    0
    Uploads
    0
    El caso es que estoy haciendo una aplicación que se conecta a un Servidor FTP, en este caso a uno que he creado con Filezilla Server, y cuando quiero leer todo el contenido del socket hasta que este este vacío, este se queda como esperando en lugar de darse cuenta de que no hay datos. He estado leyendo y parece ser que el readLine() del BufferedReader es bloqueante y bloquea el socket. Quisiera saber que tengo que hacer. Coloco un ejemplo en java de lo que quiero hacer:

    Código:
    import java.io.BufferedReader;
    import java.io.DataInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    public class Cliente {
    	public static void main(String[] args) {
    		try{	
    				Socket sControl = new Socket("192.168.1.14", 21);
    				System.out.println("Establecida conexión de control.");
    				
    				PrintStream salidaControl = new PrintStream(sControl.getOutputStream(),true);
    				BufferedReader entradaControl = new BufferedReader(new InputStreamReader(sControl.getInputStream()));
    				
    				System.out.println(entradaControl.readLine());
    				
    				salidaControl.println("USER yo");
    				System.out.println(entradaControl.readLine());
    				
    				salidaControl.println("PASS 4488");
    				System.out.println(entradaControl.readLine());
    				
    				salidaControl.println("HELP");
    				
    				String line;
    				while(true){
    					line = entradaControl.readLine(); //Aquí se queda esperando que le llegue algo para leer
    					if(line != null)
    						System.out.println(line);
    					else
    						break;
    				}
    				
    				System.out.println("FUERA");
    				
    		}catch (IOException e) {
    			System.out.println("Error en el cliente");
    		}
    	}
    }
    Espero que me puedan ayudar. Un saludo.
    Citar  
     

  2. #2  
    Moderador Global
    Fecha de ingreso
    Jul 2005
    Ubicación
    1, 11, 21, 1211...
    Mensajes
    1.568
    Descargas
    58
    Uploads
    0
    Por lo que cuentas, quieres convertir una comunicación síncrona en asíncrona para así evitar el bloqueo de readLine()... esto lo puedes conseguir reordenando un poco tu bucle, de la siguiente manera:

    Código:
    while (true){
        while ((line=entradaControl.readLine()) != null){
            System.out.println(line);
        }
    }
    Pruébalo y comenta.

    Un saludo.
    El optimista tiene ideas, el pesimista... excusas

    Citar  
     

  3. #3  
    Iniciado
    Fecha de ingreso
    Feb 2012
    Mensajes
    4
    Descargas
    0
    Uploads
    0
    Si mi idea es esa, pero sigue igual que antes, se queda esperando leer algo.
    Citar  
     

  4. #4  
    Moderador Global
    Fecha de ingreso
    Jul 2005
    Ubicación
    1, 11, 21, 1211...
    Mensajes
    1.568
    Descargas
    58
    Uploads
    0
    Ok, pues entonces la forma más fácil es que te implementes una solución multihilo, haciendo uso de la clase Thread de Java, de tal forma que al llamarlo, se mantenga un segundo hilo realizando el bucle while(true). Así el hilo se mantendrá "bloqueado" a la espera de recibir un caracter, y el hilo asociado al main de tu proceso, quede liberado de esta tarea.

    Un saludo.
    El optimista tiene ideas, el pesimista... excusas

    Citar  
     

  5. #5  
    Avanzado
    Fecha de ingreso
    Jan 2004
    Ubicación
    Argentina
    Mensajes
    427
    Descargas
    1
    Uploads
    0
    Aca te dejo una solucion:

    cliente.class

    Código:
    import java.io.BufferedReader;
    import java.io.DataInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    public class cliente {
    	public static BufferedReader entradaControl;
    	public static void main(String[] args) {
    		try{	
    				System.out.println("Iniciando conexión de control...");
    				Socket sControl = new Socket("192.168.1.14", 21);
    				System.out.println("Establecida conexión de control.");
    				PrintStream salidaControl = new PrintStream(sControl.getOutputStream(),true);
    				 entradaControl = new BufferedReader(new InputStreamReader(sControl.getInputStream()));		
    				pantalla p = new pantalla();
    				p.start();
    				
    				salidaControl.println("USER yo");
    				
    				salidaControl.println("PASS 4488");
    				
    				salidaControl.println("HELP");
    				salidaControl.println("STAT");
    				
    				// Si usas system out capaz se vean antes por el tema del sicro
    				
    		}catch (IOException e) {
    			System.out.println("Error en el cliente");
    		}
    	}
    }
    pantalla.class

    Código:
    import java.io.IOException;
    
    public class pantalla extends Thread
    {
       public void run()
       {
    	   
    		while(true){
    			try {
    				System.out.println(cliente.entradaControl.readLine());
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    						
    		}
    		
       } 
    }
    <<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>
    No llores porque termino, sonrie porque sucedio-.
    Citar  
     

  6. #6  
    Iniciado
    Fecha de ingreso
    Feb 2012
    Mensajes
    8
    Descargas
    0
    Uploads
    0
    Hola, estoy haciendo algo parecido y me surge una duda, ¿por qué en pantalla.class declara el metodo run y luego en el main se llama a p.start()? ¿no sería más logico llamar a p.run()?
    Citar  
     

  7. #7  
    Avanzado
    Fecha de ingreso
    Oct 2010
    Mensajes
    377
    Descargas
    23
    Uploads
    0
    Algun dia tendre que aprender algo de JAVA se ve todo tan limpio, que bonito.
    Bendo mi cuelpo, xicaz interezadaz mnanden priBado, no ravoz ni zorpesas.
    Citar  
     

  8. #8  
    Moderador Global
    Fecha de ingreso
    Jul 2005
    Ubicación
    1, 11, 21, 1211...
    Mensajes
    1.568
    Descargas
    58
    Uploads
    0
    Hola, estoy haciendo algo parecido y me surge una duda, ¿por qué en pantalla.class declara el metodo run y luego en el main se llama a p.start()? ¿no sería más logico llamar a p.run()?
    Si llamas al método run() de la clase Thread de java, lo que harás será tener un hilo que se ejecuta secuencialmente, por lo tanto, el resultado final será una ejecución síncrona.

    Llamando al método start() de esta misma clase, lo que haces es que el hilo se lance en paralelo, logrando por tanto una ejecución asíncrona.

    En una clase que herede de Thread o implemente Runnable, sobreescribes el método run(), añadiendo la función que deseas ejecutar en paralelo. Al llamar a start(), éste ya se encarga de llamar a run(), para ejecutar esa función, por eso no es necesario sobreescribir start().


    Algun dia tendre que aprender algo de JAVA se ve todo tan limpio, que bonito.
    Apréndelo, pero por favor, no lo utilices si no es por obligación :sss. Hoy en dia existen miles de tecnologías, mucho más potentes que java, mucho más rápidas, eficientes y fáciles de aprender, entender y mantener.

    Si Java se utiliza para un nuevo proyecto, entonces se puede garantizar, casi con certeza, que los desarrolladores implicados en ese proyecto, que hayan aceptado hacerlo en java, son reacios a aprender un nuevo lenguaje, porque piensan que con java se puede hacer todo... y claro, ¿para qué aprender algo nuevo si con lo que ya sé, puedo hacerlo igual?. Créeme, "igual" no!!! El tiempo de desarrollo que inviertes picando código java, lo inviertes aprendiendo otras tecnologías, y lo que en java son 10 - 20 líneas, probablemente en esa otra tecnología sea 1 sola línea... y no te exagero, 1 linea tal cual...

    Otros piensan que si hacen software libre en java, tendrá más adeptos porque casi el 90% de los programadores, saben java y esta es en realidad una buena razón para utilizar java... aunque muy triste.

    En la mayoría de los casos, se sigue utilizando java porque simplemente es por necesidades del cliente... un producto fue en su dia desarrollado en java, y actualmente migrar a otra tecnología es más costoso que seguir dando mantenimiento en java, y probablemente este sea el problema de por qué se sigue utilizando hoy dia.

    Un saludo.
    Última edición por hystd; 28-02-2012 a las 20:49
    El optimista tiene ideas, el pesimista... excusas

    Citar  
     

  9. #9  
    Iniciado
    Fecha de ingreso
    Feb 2012
    Mensajes
    4
    Descargas
    0
    Uploads
    0
    Muchas gracias por contestar y por las soluciones. Mañana lo miro.

    Un saludo.
    Citar  
     

  10. #10  
    Iniciado
    Fecha de ingreso
    Feb 2012
    Mensajes
    4
    Descargas
    0
    Uploads
    0
    Encontre otra posible forma de solucionarlo, sería estableciendo el tiempo de espera del readLine() con .setSocketTimeout() y así si después de esperar no llega nada elimina el bloqueo:

    Código:
    import java.io.BufferedReader;
    import java.io.DataInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.io.PrintWriter;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    public class Cliente {
    	PrintStream salidaControl = null;
    	BufferedReader entradaControl = null;
    	
    	public void run(){
    		try{	
    			Socket sControl = new Socket("192.168.1.14", 21);//;
    			sControl.setSoTimeout(6000); //Digo cuál será el tiempo de espera
    			System.out.println("Establecida conexión de control.");
    		
    			salidaControl = new PrintStream(sControl.getOutputStream(),true);
    			entradaControl = new BufferedReader(new InputStreamReader(sControl.getInputStream()), 8192);
    			
    			System.out.println(entradaControl.readLine());
    			
    			salidaControl.println("USER yo");
    			System.out.println(entradaControl.readLine());
    			
    			salidaControl.println("PASS 4488");
    			System.out.println(entradaControl.readLine());
    			
    			salidaControl.println("HELP");
    			leer();
    			System.out.println("SALGO");
    		}catch (IOException e) {
    			System.out.println("Error en el cliente");
    		}
    	}
    	
    	public void leer(){
    		try {
    			String line;
    			while(true){
    					line = entradaControl.readLine();
    				
    				if(line != null)
    					System.out.println(line);
    				else
    					break;
    			}
    		} catch (IOException e) {
    			System.out.println("Se agoto el tiempo de espera de lectura.");
    		} //Aquí se queda esperando que le llegue algo para leer
    	}
    	
    	
    	public static void main(String[] args) {
    		new Cliente().run();
    	}
    }
    
    Esta forma sería valida no? Es decir, funcionar funciona porque lo miré, pero será muy sucio hacer esto, será un apaño, o sería una forma correcta de hacerlo?
    
    Un saludo.
    Citar  
     

Marcadores
Marcadores
Permisos de publicación
  • No puedes crear nuevos temas
  • No puedes responder temas
  • No puedes subir archivos adjuntos
  • No puedes editar tus mensajes
  •