Indy: Connection clode gracefully. Completas causas y solución ?
Hola,
Perdón por abrir esto como un hilo nuevo cuando no solo hay hilos antiguos sino que hace pocas horas se acaba de cerrar uno al respecto (vease http://www.clubdelphi.com/foros/showthread.php?t=53705); pero, en esos hilos el objetivo fué resolver el problema de alguién y creo en cambio que el problema amerita una discusión general Yo también me he encontrado muy recientemente con el error "Connection closed gracefully" (tengo Delphi 2007 Update 3 con Indy 10) Una investigación en Internet indica que el error es frecuente, tan frecuente que incluso un miembro del equipo Indy escribió una larga explicación al respecto, la cual puede consultarse aquí: http://www.swissdelphicenter.ch/en/showarticle.php?id=1 Cuando se pregunta por este problema, quienes contestan usualmente mandan a leer esa nota; pero, hay varios inconvenientes con ella que creo ameritan un hilo especial: La explicación es teóricamente extensa y se puede decir que buena; pero, desde el punto de vista práctico, no explica los puntos más importantes que necesitamos tener en cuenta los programadores. Antes todo, aclaro que el principal consejo que se dá es para que el mensaje no moleste cuando se está depurando; pero, en mi caso, y supongo que a otros también les ha pasado, el problema no lo tenía al depurar, sino en la versión "productiva". Un punto clave que no explica es como detectar la verdadera causa del error. Veamos : El caso en que se dispare en un servidor, puede ser un verdadero error, o una exception. Yo no le experimentado; pero, la nota no dice como saber cuando es un error y cuando una excepción. El caso de que el mensaje se dispare en un cliente (en mi caso se dispara al llamar al método Get de TIdHTTP), dice que corresponde a un verdadero error y debe ser manejado atrapandolo; sin embargo, no explica exactamente que causa el error. En ambos casos, la explicación general es que se trata de que al menos uno de los dos equipo cierra la conexión, y que en algunos protocolos es algo normal, parte de su propia convención. En mi caso, esa explicación general no la encuentro aplicable porque de casi 100 llamadas distintas al servidor, ya he probado la gran mayoría y solo en una se presenta, y con mucha frecuencia. Si correspondiera a esa explicación debería ocurrir en bastantes más llamadas. Concluyo que en mi caso es un verdadero error; pero, por qué ?, en cuales circunstancias ?. Por qué el comando a veces funciona y a veces no (en especial siendo uno en que la operación es corta) ?. La nota no dá ninguna pista clara para responder esto. Ahora bien, tampoco explica como debe exactamente manejarse el error. Yo he implementado una solución usando un contador de intentos; así, si se produce el error, incremento el contador y repito la llamada. Logicamente si excede el máximo de intentos (lo ajusté a 4), lo tomó como un problema definitivo y reporto al usuario. Este enfoque me ha funcionado muy bien; pero, por un lado, en la llamada del problema, el tiempo de respuesta no es bueno (claramente, con frecuencia se necesitan varios intentos), por otro lado, ese tipo de solución a "prueba y error" no me parece confiable, ni presentable desde el punto de vista técnico. De hecho, en el fondo es similar a la solución dada en otro hilo usando en "delay" entre llamadas. En otros hilos y notas al respecto, he visto mencionar como causa la versión de Indy; pero no parece ser algo directamente relacioando con la versión. Ojalá puedan comentar al respecto, a ver si puede aclararse el tema. |
Cita:
Cita:
Cita:
Cita:
Un cliente HTTP robusto deberá procesar correctamente todas las respuestas probables de un servidor, y no esperar tener únicamente status 200. Cita:
Yo relaciono mensajes de error "connection closed gracefully" con la versión debido a que en versiones de INDY 9 previas a la 9.0.18 (ya no logro recordar en cuales exactamente), esta excepción particular no era bien manejada internamente dentro de INDY, por lo que salía al exterior cuándo no existía realmente o era posible manejarla. Hasta luego. ;) |
Gracias. Comentarios
Hola,
Muchas gracias por las respuestas. Tengo varios comentarios: 1. Cuando yo hablo de que no explica como detectar la verdadera causa del error me refiero a que, si alguno de los lados cierra la conexión, debe ser por un motivo. Uno, el caso normal que no debe considerarse como error, lo explican como causado por la misma convención del protocolo; pero, el otro, o sea cuando es un verdadero error, no explican que puede causarlo ni como detectarlo en nuestro código, ya que decir que uno de los dos lados cierra la conexión es indicar la manifestación final; pero no la causa original. Para ponerlo más claro en términos de códigos, lo ilustro con mi metodología: Cuando tengo una serie de llamadas anidadas, en cada una de las cuales se pueden producir errores, yo voy atrapandolos en cada una de ellas, y lo hago con un mensaje que muestra un código de error y una descripción del mismo correspondiente al bloque; al final incluyo, el error que viene de la rutina inmediatamente anidada. De esta forma, el mensaje final de error es largo (incluso 4 o 5 anidados); pero permite determinar la ruta exacta del error. Según la explicación dada para este problema de conexión, aparentemente se dispara el mensaje más interno y no se incluye ninguna información de porque o donde se generó. Igualmente, no indica que deberíamos revisar cuando se trate de verdaderos errores. Por lo anterior, aún cuando he leído con cuidado los mismos parrafos que publicas de esa nota (y toda la nota), no estoy de acuerdo en que sea una explicación completa para la situación. 2. Mi código para atrapar errores es metodológicamente muy robusto, como habrás notado de la observación anterior. En mi caso, aparte de desplegar mensajes de error largos, no solo atrapo los códigos de error propios de la convención; sino que también una serie de códigos de error personalizados que envío para detectar acciones que requieren manejo especial. De hecho, atrapo todo lo posible, no solo lo probable. En el caso de nuestro mensaje, la excepción se dispara; pero el servidor está enviando el código 200. Debido a eso, inicialmente me sorprendió porque no estaba usando el "Exception" para analizar el mensaje, sino que cuando atrapaba la excepción, solo validaba usando ResponseText y ResponseCode. Obviamente, ya cambié ese código porque ya no confío exclusivamente en los códigos de error del servidor. 3. Cuando dices: Cita:
4. He usado, y uso, las versiones 8, 9 y 10 de Indy. En este momento, el problema se presenta en la versión 10 que viene con el Update 3 de Delphi. De todas formas, cuando digo que no parece algo relacionado con la versión es porque me pasa con la última (o casi última, no me he fijado si sacaron algo más) y he leído referencias de personas que lo han sufrido en diversas versiones. 5. Veo que no comentastes nada acerca de como manejarlo ?. Que metodología usas ? Muchos saludos |
Yo tambíen me tropecé con este error recientemente. La solución lo leí en otro foro.
Utilizo C++Builder 6 con componentes Indy 9.17x pero creo que funciona para versiones superiores también Ejemplo de código: Código PHP:
|
La franja horaria es GMT +2. Ahora son las 02:20:21. |
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