Club Builder - Foros de discusión Club Builder
Foro de C++Builder en español
 
 FAQFAQ   BuscarBuscar   MiembrosMiembros   Grupos de UsuariosGrupos de Usuarios   RegistrarseRegistrarse 
 PerfilPerfil   Entra para ver tus mensajes privadosEntra para ver tus mensajes privados   EntrarEntrar 

Error si falla la red

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Bases de Datos
Ver tema anterior :: Ver tema siguiente  
Autor Mensaje
Mensaje    Asunto: Error si falla la red Responder citando

Tengo un problema con Interbase trabajando en RED.
Si mi aplicación está conectada a una BDD que se encuentra en otro PC de la RED y esta, se desconecta por un fallo en la red eléctrica, o la Red se cae durante mas de 50 milisegundos por cualquier motivo, como desconectar el cable de red, mi aplicación me da el siguiente error:


Unable to complete network request to host “Barebone:3050”.
Error reading data from the connection.
Se ha forzado la interrupción de una conexión existente por el host remoto.


Este Error lo capturo de este modo con el ‘EIBInterBaseError’ de la siguiente manera:

Código:

//En el Form de Base de datos pongo esto:
__fastcall TMDatos::TMDatos(TComponent* Owner)
      : TDataModule(Owner)
{
   Application->OnException = ErrorServidor;
}


Y la funcion ‘ErrorServidor’ contiene esto:

Código:

void __fastcall TMDatos::ErrorServidor(TObject *Sender, Exception *E)
{
   //si es una excepcion de interbase
   if(E->ClassNameIs("EIBInterBaseError"))
   {
      EIBInterBaseError *ErrorIB = reinterpret_cast<EIBInterBaseError>(E);

      // si realmente es de interbase, tratamos el codigo de error
      if(ErrorIB->SQLCode == -902)
      {
         ShowMessage(
         "Su RED ha sufrido un Corte de Luz,\n"
         "o su RED no es Consistente contra Fallos de Conexión.\n\n"
         "TPVBarman Pro, tiene que desconectarse del Servidor.\n"
         "Saldrá del Programa, para evitar un mal mayor.");

         Application->Terminate();// Salir del programa con Error
         exit(0);
      }
   }
   else
      ShowMessage(E->Message);
}


Con esta función capturo el error -902 de ErrorIB->SQLCode,
Tambien puedo capturar el error en si mismo comprobando el valor devuelto por ‘ErrorIB->IBErrorCode’ que es 335544721 así:

Código:

If(ErrorIB->IBErrorCode == 335544721)
{
   //Intenta conectar otra vez.
}


El problema es que si sigo insistiendo el programa de da otro error del Builder que dice:
‘Dataset open’

Resumiendo:

¿Como puedo hacer para que si La RED se cae por cualquier motivo, mi aplicación vuelva a funcionar cuando la red vuelva a ser operativa?


Lo que me gustaría hacer es esto:
Código:

void __fastcall TMDatos::ErrorServidor(TObject *Sender, Exception *E)
{
   //si es una excepcion de interbase
   if(E->ClassNameIs("EIBInterBaseError"))
   {
      EIBInterBaseError *ErrorIB = reinterpret_cast<EIBInterBaseError>(E);

      // si realmente es de interbase, tratamos el codigo de error
      if(ErrorIB->SQLCode == -902)
      {
         if(MessageDlgPos("TPVBarman Pro...\n\n"
         "Su RED ha sufrido un Corte de Luz,\n"
         "o su RED no es Consistente contra Fallos de Conexión.\n\n"
         "¿Quiere Reintentar la Conexión?"",
         mtConfirmation, TMsgDlgButtons() << mbNo <<mbOK>Left + 290, frmVentas->Top + 300)== mrOk)
         {
             IBDatabase->Close();
             IBDatabase->Open();
         }
         else
            {
               Application->Terminate();// Salir del programa con Error
               exit(0);
             }
      }
   }
}


Pero no funciona. Alguna Sugerencia al respecto...
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

Hola Jésus, este post no lo había visto.

Mira a veces es casi imposible detectar cuando el cable de red ha fallado pues este tema es el "Media Sense" de Windows, pero he realizado una trampa cuando se esta Accediendo a la parte de Edición es decir cuando el usuario esta en el proceso de grabación que bien puede servirte para lo que estas implementando, te explico mi problema y la manera de como solucionarlo.

Uno de los problemas que encontre cuando intenté trasferir 165 mil registros de una base de Dbase a Interbase/Firebird

Fueron los siguientes.
Cuando estaba transfiriendo la información en un equipo, este tardaba aproximadamente 3 hrs, así que desidí instalar una maquina Virtual (Virtual PC 2007 de Windows o VMWare de prueba) para crear un segundo equipo usando parte del HardWare del mio.

realizando la prueba y dividiendo el numero de registros. inicio las transferencias, la mitad de registros en el mio y la otra mitad de registros en el equipo virtual conectados a la misma base ( una mini red funcionable)

cuando uno de los equipos termina pues ha transferido todos, me di cuenta que en el otro equipo, me saltaba una excepción indicandome que no estaba en modo Edicion. me extrañé pues según mi programación la forma de hacerlo es correcta.

Revisé y revisé y el código estaba correcto. no asi, cuando detectaba que la red se habia desconectado o se aplicaban las transferencias. pues al cerrar en una Estacion, la otra automaticamente tambien cerraba las transacciones (uso eventos para notificar que hay cambios y asi reflejarlos directamente en TODAS las estaciones).

para no hacer grande este post, tuve el mismo problema que mencionas, y dije "mmm con try ... catch" pero no sabia como meterlo. asi que decidi hacer lo siguiente.

Analicé mi algoritmo y esto era lo que hacia.

Código:
1.- abrir la tabla de Dbase
2.- ir al primer registro de la tabla de Dbase
3.- Ejecutar hasta que no llegue al final de la tabla de Dbase.
4.- Insertar un registro en la tabla de Interbase-firebird (previa apertura)
5.- Actualizar los campos en la tabla de Int-Fire, con la info de la T-Dbase
6.- Grabar en interbase-Firebird (post, applyupdate, commitretainig)
7.- Ir al siguiente Registro de la tabla de Dbase (next)
8.- Fin del ciclo del punto (3)


Según yo, esto era lo correcto y a simple vista así es.
pero cuando una de las estaciones terminaba, cerraba la transaccion antes que la otra terminara, saltandome una excepcion en el punto 5 del algoritmo diciendome que la red se habia perdido o que no estaba en modo edicion.
A fin de cuentas lo que hice fue lo siguiente, agregue un nuevo ciclo de la siguiente manera



Código:
1.- abrir la tabla de Dbase
2.- ir al primer registro de la tabla de Dbase
3.- Ejecutar hasta que no llegue al final de la tabla de Dbase.
4.- Insertar un registro en la tabla de Interbase-firebird (previa apertura)(Edit() o Insert())

   while(1) // ejecutar siempre
   {
       try
      {
         // si hay un error lo atrapo y me voy al catch(...)
         5.- Actualizar los campos en la tabla de Int-Fire, con la info de la T-Dbase
         6.- Grabar en interbase-Firebird (post, applyupdate, commitretainig)
         // si llegaba a este punto quiere decir que el registro
         // se ha grabado correctamente por lo tanto se interrumpe
         // el ciclo infinito.
         break; // al salir ivamos al next para el siguiente registro
          // de la tabla de Dbase paso No. 7
      }
      catch(...)
      {
         // aqui capturaba la exepcion, pero lo unico que hacia, es
         // activar nuevamente la edicion
         TablaFirebird->Edit();
      }
   }

7.- Ir al siguiente Registro de la tabla de Dbase (next)
8.- Fin del ciclo del punto (3)


y asi fue como solucioné el error de la conexion cortada o de conflictos
dentro de las tablas cuando una terminaba, pues este ciclo infinito
while(1) hace que la tabla siempre este en modo edicion.

en tu caso puedes hacer lo mismo y validar con un MessageDlg() == <Resultado boton>
dentro de la parte del catch(...) y mostrarle al usuario algo como
Código:
|-----------------------------------------|
|  (!)  La red se ha caido                |
|                                         |
|     [Reintentar]   [Cancelar]           |
|-----------------------------------------|


Si elige el boton Cancelar pues usas un break para salir del ciclo
y un rollback para cancelar las transacciones pendientes.

si desides usar el Reintentar pues no haces nada y lo regresas al ciclo
infinito.

Espero que esta pueda darte una idea y por que no una solucion al problema del cable caído o "No esta en modo Edit"

Saludos.
_________________
Cool
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email MSN Messenger
Mensaje    Asunto: Responder citando

Gracias Cesar, ya habia implementado algo parecido con un mensaje al usuario, "Cancelar Reintentar".
Ahora estoy aprendiendo PHP. Saludos.
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mostrar mensajes de anteriores:   
Cambiar a:  
No puedes publicar temas nuevos en este foro
No puedes responder a temas en este foro
No puedes editar tus mensajes en este foro
No puedes borrar tus mensajes en este foro
No puedes votar en las encuestas de este foro


Hosting WordPress Indedmedia desde 3,99 €
© 2002–2026 Club Builder · Funciona con phpBB.