Comunicación asincrona que no avisa cuando se pierde la comunicación con el Ho st

30/11/2004 - 09:06 por BigSus | Informe spam
Buenos dias.

Tengo que conectar mi programa a una máquina y lo hago de forma asincrona.
La máquina hace de servidor, así que yo tengo que conectar con ella
siempre que este arrancada.
Mi problema es que cuando apagan la máquina no se lanza ninguna
excepción y mi programa se queda
esperando a recibir datos indefinidamente de una conexión que ya no existe.
Me hace falta recoger la desconexión cuando se produce para reiniciar el
proceso de comunicación. No me vale hacer ping porque el host se puede
apagar y encender en muy pocos segundos.

Este es mi código principal:

public void Conectar()
{
try
{
tcpClient = new TcpClient(ip.ToString(),puerto);
tcpClient.ReceiveBufferSize24;
tcpClient.ReceiveTimeoute;

networkStream=tcpClient.GetStream();
buff = new byte[1024];
cbRead = new AsyncCallback(CuandoLecturaCompleta);
//<-Preparo la conexión
if(eventoEstadoConexion!=null)
eventoEstadoConexion(true);
ComenzarALeer(); //<-Comienzo la conexión
}
catch(System.Net.Sockets.SocketException se)
{
if(eventoError!=null)
eventoError(se,"Host inaccesible");
}
catch(Exception se)
{
if(eventoError!=null)
eventoError(se,"Excepción preparando la conexión");
}
}

private void ComenzarALeer() //<=Empezar a leer de forma asincrona
{
try
{
//Cuando se reciben datos esto los manda a la función
'CuandoLecturaCompleta'.
//En caso de que la máquina se desconecte nunca mas
recibe nada la función
// 'CuandoLecturaCompleta', pero tampoco se lanza
ninguna excepción

iasync=networkStream.BeginRead(buff,0,buff.Length,cbRead,null);
}
catch(Exception se)
{
if(eventoError!=null)
eventoError(se,"Excepción comenzando a leer");
}
}

private void CuandoLecturaCompleta( IAsyncResult ar)
{
try
{
int bytesRead = networkStream.EndRead(ar);
if ( bytesRead > 0)
{
string s =
System.Text.Encoding.ASCII.GetString(buff, 0, bytesRead);

//Aqui enviamos los datos mediante el evento en
caso de que haya sido instanciado
if(eventoDatosRecibidos!=null)
eventoDatosRecibidos(s.Substring(0,bytesRead));
ComenzarALeer(); //Seguimos leyendo
}
else
{
//Se ha cortado la conexión
CerrarConexion();
if(eventoEstadoConexion!=null)
eventoEstadoConexion(false);
}
}
catch(System.IO.IOException se)
{
CerrarConexion();
if(eventoEstadoConexion!=null)
eventoEstadoConexion(false);
}
catch(Exception se)
{
if(eventoError!=null)
eventoError(se,"Excepción recibiendo mensaje");
}
} //CuandoLecturaCompleta

Cuando comenzé el desarrollo, la comunicación la realizaba de forma
sincrona y cuando el host se desconectaba recibía un mensaje vacio. El
problema era que me comía todos los recursos de la máquina, ya que tengo
que estar continuamente mirando si hay nuevos mensajes.

¿Alguien sabe como recoger el evento de desconexión del host con este
tipo de comunicación?

Un Saludo
 

Leer las respuestas

#1 pablo crosio
30/11/2004 - 21:47 | Informe spam
hola!

una idea que se me ocurre es que utilices el iasync devuelto por BeginRead:

iasync=networkStream.BeginRead(buff,0,buff.Length,cbRead,null);

y tomes su propiedad AsyncWaitHandle, con ella podrias realizar esperas
(WaitOne) con un timeout especfico (tal vez un toco y me voy para ver el
estado) y una cantidad n de veces. es cierto que esto bloquea tu thread
pero tambien podrias realizar la espera en un nuevo thread esto lo
podrias realizar hasta que culminara la operacion o hasta que luego de n
intentos de espera no pase nada
esta forma no deberia consumir recursos de maquina, al menos las funciones
de espera de eventos de la API win32 no lo hacen

una forma alternativa es trabajar con el socket cliente en un nuevo thread
en forma sincronica y bloqueante (Read bloquea si no hay datos para
leer). si se corta la conexion... como decis vos devuelve vacio... y fin
... sino haces lo que tenes que hacer con los datos...

de esta forma tendrias tu thread principal sin bloquearse y tu thread de
trabajo conectandose con el servidor obviamente deberias tener una forma
de coordinar cuando termino de trabajar el thread y avisar al prinicipal
algun evento... callback... flags... etc etc

espero te sirva

salu2!!

pablo



"BigSus" escribió:

Buenos dias.

Tengo que conectar mi programa a una máquina y lo hago de forma asincrona.
La máquina hace de servidor, así que yo tengo que conectar con ella
siempre que este arrancada.
Mi problema es que cuando apagan la máquina no se lanza ninguna
excepción y mi programa se queda
esperando a recibir datos indefinidamente de una conexión que ya no existe.
Me hace falta recoger la desconexión cuando se produce para reiniciar el
proceso de comunicación. No me vale hacer ping porque el host se puede
apagar y encender en muy pocos segundos.

Este es mi código principal:

public void Conectar()
{
try
{
tcpClient = new TcpClient(ip.ToString(),puerto);
tcpClient.ReceiveBufferSize24;
tcpClient.ReceiveTimeoute;

networkStream=tcpClient.GetStream();
buff = new byte[1024];
cbRead = new AsyncCallback(CuandoLecturaCompleta);
//<-Preparo la conexión
if(eventoEstadoConexion!=null)
eventoEstadoConexion(true);
ComenzarALeer(); //<-Comienzo la conexión
}
catch(System.Net.Sockets.SocketException se)
{
if(eventoError!=null)
eventoError(se,"Host inaccesible");
}
catch(Exception se)
{
if(eventoError!=null)
eventoError(se,"Excepción preparando la conexión");
}
}

private void ComenzarALeer() //<=Empezar a leer de forma asincrona
{
try
{
//Cuando se reciben datos esto los manda a la función
'CuandoLecturaCompleta'.
//En caso de que la máquina se desconecte nunca mas
recibe nada la función
// 'CuandoLecturaCompleta', pero tampoco se lanza
ninguna excepción

iasync=networkStream.BeginRead(buff,0,buff.Length,cbRead,null);
}
catch(Exception se)
{
if(eventoError!=null)
eventoError(se,"Excepción comenzando a leer");
}
}

private void CuandoLecturaCompleta( IAsyncResult ar)
{
try
{
int bytesRead = networkStream.EndRead(ar);
if ( bytesRead > 0)
{
string s =
System.Text.Encoding.ASCII.GetString(buff, 0, bytesRead);

//Aqui enviamos los datos mediante el evento en
caso de que haya sido instanciado
if(eventoDatosRecibidos!=null)
eventoDatosRecibidos(s.Substring(0,bytesRead));
ComenzarALeer(); //Seguimos leyendo
}
else
{
//Se ha cortado la conexión
CerrarConexion();
if(eventoEstadoConexion!=null)
eventoEstadoConexion(false);
}
}
catch(System.IO.IOException se)
{
CerrarConexion();
if(eventoEstadoConexion!=null)
eventoEstadoConexion(false);
}
catch(Exception se)
{
if(eventoError!=null)
eventoError(se,"Excepción recibiendo mensaje");
}
} //CuandoLecturaCompleta

Cuando comenzé el desarrollo, la comunicación la realizaba de forma
sincrona y cuando el host se desconectaba recibía un mensaje vacio. El
problema era que me comía todos los recursos de la máquina, ya que tengo
que estar continuamente mirando si hay nuevos mensajes.

¿Alguien sabe como recoger el evento de desconexión del host con este
tipo de comunicación?

Un Saludo

Preguntas similares