Foros del Web » Programación para mayores de 30 ;) » Java »

Gurus sobre Sockets - Detectar conexion perdida.

Estas en el tema de Gurus sobre Sockets - Detectar conexion perdida. en el foro de Java en Foros del Web. Buenas tardes de nuevo Foreros Javeros, jeje !!! Pregunta compleja, que resolvi en .NET, resolvi en C y.... el colmo que en Java parece que ...
  #1 (permalink)  
Antiguo 29/01/2008, 09:52
 
Fecha de Ingreso: junio-2003
Ubicación: Asturias
Mensajes: 2.429
Antigüedad: 20 años, 10 meses
Puntos: 7
Gurus sobre Sockets - Detectar conexion perdida.

Buenas tardes de nuevo Foreros Javeros, jeje !!!


Pregunta compleja, que resolvi en .NET, resolvi en C y.... el colmo que en Java parece que es diferente !!!


En C# .NET tengo el siguiente codigo
Código:
        private void DatosLlegados(IAsyncResult iAr)
        {
            Socket objSocket = (Socket)iAr.AsyncState;
            try
            {
                int tamanioDatosRecibidos = objSocket.EndReceive(iAr);
                if (tamanioDatosRecibidos > 0)
                {
                    byte[] bytesDatosReales = new byte[tamanioDatosRecibidos];
                    Array.Copy(bytesDatos, bytesDatosReales, tamanioDatosRecibidos);
                    string txtDatosReales = Encoding.ASCII.GetString(bytesDatosReales);

                    if (DatosRecibidos != null)
                    {
                        string ipClienteConectado = ((IPEndPoint)objSocket.RemoteEndPoint).Address.ToString();
                        int puertoClienteConectado = ((IPEndPoint)objSocket.RemoteEndPoint).Port;
                        this.DatosRecibidos(objSocket, ipClienteConectado, puertoClienteConectado, txtDatosReales);
                    }

                    objSocket.BeginReceive(bytesDatos, 0, bytesDatos.Length, SocketFlags.None, new AsyncCallback(DatosLlegados), objSocket);
                }
                else
                {
                    EliminarCliente(objSocket);
                }
            }
            catch (SocketException exSocket)
            {
                if (exSocket.SocketErrorCode == SocketError.ConnectionReset)
                    EliminarCliente(objSocket);
                else
                {
                    if (DatosErrores != null)
                        this.DatosErrores(MethodBase.GetCurrentMethod().Name, exSocket.Message);
                }
            }
            catch (Exception ex)
            {
                if (DatosErrores != null)
                    this.DatosErrores(MethodBase.GetCurrentMethod().Name, ex.Message);
            }
        }

Como podeis ver al principio del codigo tengo la condicion " if (tamanioDatosRecibidos > 0) ", en la cual ya puedo detectar si ha habido una desconexión (Probocada o no). Con mi cliente java, me conecto a mi servidor .NET, cierro inesperadamente mi cliente java y el servidor ya detecta que ha habido una desconexión. (Sin necesidad de implementar pings, keepalive ni nada).


Bien, pues estoy intentando lo mismo con mi cliente Java, que si cierro mi servidor .NET inesperadamente el cliente detecte que ha perdido la conexion, para ello tengo el siguiente codigo:

CLIENTE JAVA
Código:
				try
				{				
					while(true)
					{							
							int tamanioRecibido = objStreamLectura.available();
							if(tamanioRecibido>0)
							{
								byte[] bytesRecibidos = new byte[tamanioRecibido];
								
								objStreamLectura.read(bytesRecibidos, 0, tamanioRecibido);
								String txtDatos = new String(bytesRecibidos);
								
								txtCaja.setText(txtCaja.getText() + txtDatos + " [PRUEBA]" + "\r\n");
								if(finalizarHebra)
									return;
							}
					}
				}
				catch (Exception e)
				{
					txtCaja.setText(e.getMessage());
				}


Como ven, lo tengo practicamente igual, solo que en este caso si a la condicion " if(tamanioRecibido > 0) " le meto un else, esta entrando constantemente por ahí aun que esté conectado. Lo que yo necesitaria es pues... que al recoger los datos disponibles " int tamanioRecibido = objStreamLectura.available(); " se quedara ahi en tiempo de espera hasta que reciba algo. En caso de desconectarse recibirá 0 y en cualquier otro caso recibirá X bytes.

En fin, espero haberme explicado y puedan resolverme el problema de detectar cuando se ha terminado la conexión. Desde ya, muchas gracias.
__________________
Charlie.
  #2 (permalink)  
Antiguo 29/01/2008, 14:16
 
Fecha de Ingreso: octubre-2003
Mensajes: 3.578
Antigüedad: 20 años, 6 meses
Puntos: 51
Re: Gurus sobre Sockets - Detectar conexion perdida.

Available en este caso no devuelve lo que tu esperas, ya que te dice los bytes que puede leer "en ese mismo momento" y no se para a esperar a recibir algo.

Aqui puedes ver un ejemplo de como se trabaja con sockets en Java:
http://java.sun.com/docs/books/tutor...entServer.html

Con algo como el read() o similares se bloquean y esperan para leer. Si el servidor cierra la conexion, lo normal es que salte una excepcion y entonces el cliente sabe que las comunicaciones "se han roto". Sin embargo, algunas veces el protocolo TCP/IP se puede cortar sin que haya notificacion de que la cosa se ha roto, por lo que siempre es bueno usar Timeouts como salvaguarda, ya que si no podria quedarse nuestro cliente infinitamente colgado esperando de un servidor que ya no esta.

Y no es algo infinitamente remoto que apenas pasa, en Internet pasa lo suficientemente a menudo como para tenerlo en cuenta. Lo digo por experiencia ;).

S!
  #3 (permalink)  
Antiguo 29/01/2008, 18:49
 
Fecha de Ingreso: junio-2003
Ubicación: Asturias
Mensajes: 2.429
Antigüedad: 20 años, 10 meses
Puntos: 7
Re: Gurus sobre Sockets - Detectar conexion perdida.

Hola amigo, en primer lugar, gracias por responder.

Un par de temas...

Código:
int tamanioRecibido = objStreamLectura.available();
Entiendo que esta línea me devuelve el num. de bytes que hay para leer, de esta forma es como puedo crear un Array de Bytes con el tamaño justo del contenido recibido.


Cita:
Iniciado por GreenEyed
Con algo como el read() o similares se bloquean y esperan para leer. Si el servidor cierra la conexion, lo normal es que salte una excepcion y entonces el cliente sabe que las comunicaciones "se han roto".

Como puedes ver amigo tengo la línea:
[CODE]objStreamLectura.read(bytesRecibidos, 0, tamanioRecibido);[CODE/]


La cual no lanza la excepción que me dices que lanzan los métodos Read(), aun que si debo reconocer que si pongo para leer un solo byte, con el método sin parámetros Read() si que lanza la excepción cuando derrepente cierro el servidor.

Quizás sea que el método Read() que estoy usando para rellenar el array de bytes lo haga de una forma asíncrona por debajo y por eso no laze la excepción ?
__________________
Charlie.
  #4 (permalink)  
Antiguo 30/01/2008, 06:47
 
Fecha de Ingreso: octubre-2003
Mensajes: 3.578
Antigüedad: 20 años, 6 meses
Puntos: 51
Re: Gurus sobre Sockets - Detectar conexion perdida.

Lo mejor es que te olvides del metodo available(), ya que no devuelve el numero total de bytes que hay para leer.
Lo habitual es leer mientras te haya devuelto algo, con un "buffer" de tamaño pre-establecido.

Crear el array de bytes "justo" no tiene mucho sentido ya que cada llamada read puede llegar con un tamaño distinto (depende del trafico de red etc.). Es decir, si un extremo envia 2048 bytes, nada garantiza que al otro lado se reciban los 2048 de golpe, que available devuelva 2048 o que puedas leerlos solo con un read(). La red es así.

Lo de que no te lance la excepcion cuando cortes las comunicaciones ahora mismo no me queda claro por que pasa, pero posiblemente sea por que o no estas en el read() cuando se produce o el read se bloque por otro motivo... como por ejemplo "fiandose" de un available() que no es.

En muchos casos, available devuelve 0 ya que es el numero de bytes que se pueden leer sin bloquearse, y si no hay nada que leer en ese momento, o lo que hay significa bloquearse, devuelve 0. Es un dato que parece que va a dar mas informacion de la que en realidad da.

S!
  #5 (permalink)  
Antiguo 30/01/2008, 07:02
 
Fecha de Ingreso: junio-2003
Ubicación: Asturias
Mensajes: 2.429
Antigüedad: 20 años, 10 meses
Puntos: 7
Re: Gurus sobre Sockets - Detectar conexion perdida.

Bueno, voy a revisar toda la aplicación nuevamente, veo que tendré que repasar los Sockets en JAVA. Por otro lado.. Es de crear un buffer pre-establecido creo que no es óptimo, ya que efectivamente nadie me garantiza lo que me va a llegar.

Quizás cree un array de bytes demasiado corto, para todos los datos que me llegan, o demasiado largo. La idea es crear el tamaño justo para cada recibimiento.

Ya que en el caso de transferencia de archivos podría ir anexando cada nuevo arrayByte recibido a un arrayByte contenedor. Pero si el arrayByte en el que recibo es de menos tamaño que lo que me llega.... malo. Y si es mayor que lo que me llega, tambien malo ya que tendré secciones vacías e inservibles.

Por eso usaba el available, pensaba que me decia los datos recibidos en ese momento.
__________________
Charlie.
  #6 (permalink)  
Antiguo 30/01/2008, 13:16
 
Fecha de Ingreso: octubre-2003
Mensajes: 3.578
Antigüedad: 20 años, 6 meses
Puntos: 51
Re: Gurus sobre Sockets - Detectar conexion perdida.

Con lo de usar un buffer fijo, no me referia a un buffer grande para almacenar lo que vas a recibir, eso es ineficiente. A lo que me referia es a un buffer pequeño unica y exclusivamente para usar en el read(...).
Ya puestos, puedes usar un BufferedInputStream que ademas aumentará el rendimiento llamandote al read solo cuando haya suficientes datos para evitar micro-llamadas.

La mayoría de ejemplos usan BufferedReader, como por ejemplo:

http://dn.codegear.com/article/31995

pero eso es por que envian cadenas de caracteres, no contenido binario puro.

S!
  #7 (permalink)  
Antiguo 30/01/2008, 14:37
 
Fecha de Ingreso: junio-2003
Ubicación: Asturias
Mensajes: 2.429
Antigüedad: 20 años, 10 meses
Puntos: 7
Re: Gurus sobre Sockets - Detectar conexion perdida.

Ok amigo, gracias, voy a revisarlo.
__________________
Charlie.
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 10:30.