Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   Socket Error # 10054 con TIdHTTP (https://www.clubdelphi.com/foros/showthread.php?t=63678)

rolandoj 26-02-2009 05:43:58

Socket Error # 10054 con TIdHTTP
 
Hola,

Espero que alguién pueda ayudar con esto.

Estoy teniendo el error "Socket Error # 10054", Connection Reset by Peer, al emitir comandos Post desde un cliente Delphi con componentes Indy TIdHTTP en Delphi 2007. Se produce después de un tiempo de trabajo y es necesario reiniciar el cliente para superar el problema, lo que obviamente es muy molesto y debo resolverlo antes de la aplicación entre a productivo

Según lo que leído en este mismo foro, y en Internet, el texto explicativo está bien; es decir, el error se produce porque el servidor está cerrando la conexión, y hay un montón de casos en los que puede ocurrir (aquí mismo lo reportaron con Ftp).

Las causas son muy variadas; desde algo tan simple como un número excesivo de clientes en el servidor hasta restricciones en un Firewall.

Digamos que la documentación es abundante en cantidad; pero desgraciadamente parece ser muy pobre en calidad, desde un punto de vista práctico.

Por ningún lado he encontrado nada acerca de como podemos identificar la causa en un caso específico ; es decir, nadie parece explicar exactamente que cosas hay que buscar en el servidor. Por ejemplo, decir que el problema puede ser el Firewal está muy bien; pero, que cosas hay que revisar en el Firewall ?

Aún más interesante es la pregunta : Hay manera de escribir código Delphi que nos pueda ayudar a identificar la causa exacta en un caso específico ?

O la alternativa : Dado quer reiniciando el programa se arregla el problema, y parece obvio que lo que realemente importa es reiniciar los componentes Indy, hay forma de reiniciarlos sin reiniciar el programa ?

Alguién podría sugerir algunas ideas prácticas para resolver este problema ?

De antemano agradezco cualquier aporte

rolandoj 02-03-2009 03:51:26

Una solución indirecta
 
Hola,

Bueno, veo que nadie sabe nada, o a nadie le interesa. De todas formas, por si en algún momento le lelga a servir a alguien, les cuento la solución que encontre:

Se trata de una solución indirecta; es decir, no pude determinar la causa específica y por ende no está resuelto como debería ser. En su lugar, lo que hago es una solución práctica : Reinicializar el software de comunicaciones en el equipo cliente:

La estructura del código Delphi es algo como esto:

Código Delphi [-]
   Intentos := 0;
   Repeat
         ItsOk := False;
         Try
            MyIdHTTP.Post(....);
            ItsOk := True;
         Except
            ....
            ...
            On E:EIdSocketError Do Begin
               ....
               ..
               Inc(Intentos);
               if E.LastError = 10054 then Begin
                  RemoveComponent(MyIdHTTP);
                  MyIdHTTP.Free;
                  MyIdHTTP := Nil;
                  MyIdHTTP := TIdHTTP.Create(Self);
               End;
            End;
            ...
            ,,
         End;
  Until (Intentos > 4) Or ItsOk;

Aquí, el truco es que atrapar primero el error 10054, lo que se hace atrapando su clase de error EIdSocketError, y luego preguntado si es el 10054.

Luego, se debe liberar el componente TIdHTTP y volver a crearlo. Aquí, el truco es usar primero RemoveComponent porque nuestro Componente está en un TDataModule, luego hay que extraerlo de ahí, antes de liberarlo con el free.

Lo del "MyIdHTTP := Nil;" no es realmente necesario dado que se reasigna enseguida; pero yo lo uso por metodología, ya que en general, al liberar memoria se debe uno asegurar que realmente quede en Nil el pointer.

No sobra comentar que en una versión de prueba le había puesto un ShowMessage que, cada vez que atrapaba al 10054, me avisaba que se había producido, así pude darme cuenta que con el truco explicado, el sistema sigue trabajando bien después de presentarse el error.

rolandoj 02-03-2009 03:52:15

Una solución indirecta
 
Hola de nuevo,

Me olvidaba, si alguien puede sugerir algo para detectar la verdadera causa del problema, sigue siendo bienvenido.

Creo que esa verdadera causa es algo que debería averiguarse, por lo que aún no considero cerrado el hilo

fide_uci 23-11-2009 06:16:25

Connection Reset by Peer
 
A mi me sucede lo mismo. Pero la verdad es que especificamente no se por que. yo he creado un Cliente/Servidor de mensajeria instantania que me trabaja de maravillas. Pero en algunas ocasiones, muy aleatorias por cierto, el cliente se me desconecta dandome ese mismo error. Dado que aun no he implementado los paquetes KEEP_ALIVE (es este caso PING-PONG o sea que el cliente le envie un paquete al servidor para que este sepa que la conexion aun permanece activa) estoy por pensar que el servidor cierra la conexion por el tiempo que demora el cliente sin enviar ningun paquete. A lo mejor esto lo controla el mismo Switch de mi centro pero eso no lo se. La verdad es que de momento no se como resolverlo. Y cuando implemente el paquete KEEP_ALIVE, si me sigue dando el mismo error, voy a tener que hacer algun truquito para que el usuario no vea el error y parezca que no ha sucedido nada. Aunque no me gustaria hacerlo asi, pero bueno que remedio. !!!

rolandoj 23-11-2009 13:54:52

Gracias por el interés. Aún sin verdadera solución
 
Cita:

Empezado por fide_uci (Mensaje 347188)
A mi me sucede lo mismo. Pero la verdad es que especificamente no se por que. yo he creado un Cliente/Servidor de mensajeria instantania que me trabaja de maravillas. Pero en algunas ocasiones, muy aleatorias por cierto, el cliente se me desconecta dandome ese mismo error. Dado que aun no he implementado los paquetes KEEP_ALIVE (es este caso PING-PONG o sea que el cliente le envie un paquete al servidor para que este sepa que la conexion aun permanece activa) estoy por pensar que el servidor cierra la conexion por el tiempo que demora el cliente sin enviar ningun paquete. A lo mejor esto lo controla el mismo Switch de mi centro pero eso no lo se. La verdad es que de momento no se como resolverlo. Y cuando implemente el paquete KEEP_ALIVE, si me sigue dando el mismo error, voy a tener que hacer algun truquito para que el usuario no vea el error y parezca que no ha sucedido nada. Aunque no me gustaria hacerlo asi, pero bueno que remedio. !!!

Hola,

Gracias por los comentarios.

Infortunadamente, nunca he tenido noticias de una verdadera solución. Para efectos prácticos, la que expliqué antes es la que uso desde entonces. Te sugiero que la utilices, ya que para el usuario es transparente (a menos que el error se repita demasiadas veces, lo que no recuerdo que me haya ocurrido).

fide_uci 23-11-2009 21:23:19

hmm, esta bien. Vere si soluciono el priblema por la otra via, si no es asi entonces usare esa que me das. Thanks !!!

kishorfarm 26-07-2010 12:18:48

Estoy en la misma situación, con la necesidad de enviar un GET periódico para actualizar una DNS dinámica. Si uso solo el GET al final me salen excepciones "Socket error # 10054".

Tu solución no es mala pero yo lo que voy a hacer es, directamente, crear y destruir el componentge TIdHTTP cada vez que tenga que hacer un GET o un POST.

On Timer (5 minutos)

Create TIdHTTP;
try
Connect TIdHTTP;
Get;
Procesado de respuesta;
finally
Disconnect TIdHTTP;
Free TIdHTTP;
end


Cuando lo pruebe ya comentaré el resultado.

rolandoj 26-07-2010 13:45:33

Debe servir; pero ...
 
Hola,

La verdad, nunca he sabido más nada del asunto. La solución que describí la uso desde entonces y siempre ha funcionado bien.

La solución que planteas no la he usado. Debe servir también; pero, si la cantidad de llamadas es significativa, probablemente la frecuencia de errores será comparativamente baja y por ello el crear, y destruír, siempre el componente será más ineficiente que reiniciarlo solo cuandio se produzca un error.

Saludos

_cero_ 22-08-2010 08:09:38

Este problema ocurre por puertos bloqueados en el firewall (o eso creo), curiosamente no ocurre cuando se intenta conectar el componente sino cuando se desconecta (de ahí a que pase después de un tiempo), la solución más feucha que sirve al menos para comprobar esto, es desactivar el firewall para que vean que ya no da el error.

Ahora a mi seme soluciono después de abrir el puerto 21 que ocupaba para un TIdFTP, prueben eso que a mi si me funciono, pero no sé porque, ya que si el puerto estuviera bloqueado no me permitiría conectar, además solo pasa en xp, porque en vista o 7 todo va de maravilla.

Pd. Me uno a la petición de que un experto en redes nos explique esta onda con el firewall.

rolandoj 22-08-2010 23:39:35

Un dato interesante
 
Hola,

Gracias por la información.

Lo del Firewall es un dato interesante. En mi caso, al menos del lado del cliente, ese no era el problema. Ahora, el servidor era remoto y yo no tenía control total; así que no hice esa prueba, quizás si era por ahí.

De todas formas, aún si fuera por el firewall, habría que saber exactamente que parámetro causa el problema, así que el hilo sigue vivo.

Por otro lado, desde un punto de vista práctico, las soluciones disponibles son efectivas. En mi caso, ha funcionado tan bien que ya ni me acordaba de este hilo.

El tema es entonces más que todo de interés académico, aunque quizás en aplicaciones que tengan una enorme carga de llamadas puede ser valioso hallar una solución mejor.

ramato79 19-01-2012 15:45:11

Hola a todos,
no se si sera tarde, pero ahi dejo lo que me paso a mi por si os sirve.

Tengo dos aplicaciones cliente / servidor para sincronizar informacion entre distintas oficinas y me daba el error # 10054 el componente servidor al cerrar la aplicación cliente.
He "descubierto" que si activo la propiedad KeepAlive del componente y realizo un post, se provoca este error y la forma de solucionarlo ha sido obligando la desconexion desde el cliente.

Os dejo el codigo en C++ que es la herramienta que uso :)
//-----------------------------
try
{
stRespuestaWeb = HTTPClientCallCenter->Post (stUrl, stDatosPOST);
stRespuestaWeb = DecodificarHtml (stRespuestaWeb); //Decodificamos la respuesta
}
__finally
{
HTTPClientCallCenter->Disconnect();
}
//-----------------------------

Saludos...
Raúl.


La franja horaria es GMT +2. Ahora son las 11:23:41.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi