HACK HiSPANO
Volver Atras   HACK HiSPANO > PROGRAMACION > PROGRAMACION DESKTOP
Actualizar esta página Problema al leer de un socket

Respuesta
 
LinkBack Herramientas Modos de Vista
  (#1) Antiguo
Iniciado
 
Posts: 4
Fecha de Ingreso: Feb 2012
Problema al leer de un socket - 26-02-2012, 15:36


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.
Responder con Cita
  (#2) Antiguo
Moderador Global
 
Posts: 1,557
Fecha de Ingreso: Jul 2005
Localización: 1, 11, 21, 1211...
27-02-2012, 00:21


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

Responder con Cita
  (#3) Antiguo
Iniciado
 
Posts: 4
Fecha de Ingreso: Feb 2012
27-02-2012, 10:56


Si mi idea es esa, pero sigue igual que antes, se queda esperando leer algo.
Responder con Cita
  (#4) Antiguo
Moderador Global
 
Posts: 1,557
Fecha de Ingreso: Jul 2005
Localización: 1, 11, 21, 1211...
27-02-2012, 19:19


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

Responder con Cita
  (#5) Antiguo
Avanzado
 
Posts: 427
Fecha de Ingreso: Jan 2004
Localización: Argentina
28-02-2012, 01:41


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-.
Responder con Cita
  (#6) Antiguo
Iniciado
 
Posts: 8
Fecha de Ingreso: Feb 2012
28-02-2012, 17:12


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()?
Responder con Cita
  (#7) Antiguo
Avanzado
 
Posts: 374
Fecha de Ingreso: Oct 2010
28-02-2012, 17:35


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.
Responder con Cita
  (#8) Antiguo
Moderador Global
 
Posts: 1,557
Fecha de Ingreso: Jul 2005
Localización: 1, 11, 21, 1211...
28-02-2012, 20:21


Cita:
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().


Cita:
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.


El optimista tiene ideas, el pesimista... excusas


Editado por hystd : 28-02-2012 a las 20:49
Responder con Cita
  (#9) Antiguo
Iniciado
 
Posts: 4
Fecha de Ingreso: Feb 2012
29-02-2012, 02:12


Muchas gracias por contestar y por las soluciones. Mañana lo miro.

Un saludo.
Responder con Cita
  (#10) Antiguo
Iniciado
 
Posts: 4
Fecha de Ingreso: Feb 2012
29-02-2012, 10:27


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.
Responder con Cita
Respuesta

Bookmarks

Herramientas
Modos de Vista

Normas
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies son On
[IMG] código esta On
Código HTML esta Off
Trackbacks are On
Pingbacks are On
Refbacks are On




Alojado en Hacheté Diseños Web

Powered by vB 3
Copyright © 1999-2013 HACK HiSPANO