socket receive example ejemplos async c# .net sockets network-programming

receive - socket tcp ip c#



Cierre todas las conexiones de red subyacentes (2)

Fondo:
Tengo un código que se conecta a un servidor para extraer datos. Sin embargo, en algún momento el programa entró en un estado en el que no se pudo conectar con el servidor. El problema que estábamos viendo era que el servidor estaba continuamente agotando el tiempo cuando intentábamos reconectarnos.

Enchufar:
Tenemos nuestro tiempo de espera establecido en los valores predeterminados utilizados por nuestro complemento de red (un complemento de Thrift). Estos valores son 100k milisegundos de tiempo de espera y 300 milisegundos de tiempo de lectura de escritura. No exactamente tiempos de espera cortos. Además, cada vez que intentamos reconectarnos, recreamos la clase del complemento, por lo que los valores que establece internamente se restablecen cada vez que intentamos reconectarnos. Creo que los tiempos de espera no son el problema. Y creo que el complemento no es el problema.

Red:
Vimos que estos tiempos de espera repetidos ocurren durante media hora. Cuando reiniciamos el servicio (no la máquina), inmediatamente volvió a estar en línea. Entonces, sé que no era un problema de red. Eso me lleva a creer que es algo en nuestro código que entra en un estado de red no válido. Además, es un estado que no podemos controlar, ya que nuestro complemento oculta todos los buenos elementos de la red, incluidos los tiempos de espera, los indicadores de mantenimiento y los grupos de conexión (entre otros). Básicamente no tenemos acceso al miembro HTTPWebReqest.

Pregunta:
Cuando nuestra configuración de red entra en este estado, intentamos cerrar todas las conexiones y volver a conectarnos al servidor. El objetivo era eliminar todas las conexiones activas para restablecer el estado en el que nos metiéramos. Sin embargo, cuando intentamos reconectarnos, obtenemos tiempos de espera en nuestra reconexión.

De alguna manera (probablemente debido a KeepAlive y TCP Pipelining, que no podemos controlar), las conexiones de red permanecen abiertas a pesar de que hemos cerrado todas las conexiones. Esto nos deja en un mal estado y nos impide ciclar nuestras conexiones con el servidor.

La pregunta:
¿Cómo puedo eliminar todas las conexiones subyacentes a un servidor para forzar una reconexión?


La arquitectura .Net subyacente mantendrá la conexión (a través de KeepAlive) para mejorar el rendimiento general de la red. La solución más fácil es simplemente configurar KeepAlive en falso en todas sus conexiones para que no mantengan esos estados inválidos. La desventaja es que aumentará su tráfico ya que tendrán que restablecer las conexiones todo el tiempo.

Además, dado que no tiene acceso al keepalive (o al objeto HTTPWebRequest), tendrá que encontrar la forma de eliminar las conexiones fuera de la configuración de solicitud.

Hay dos enfoques que puede tomar para que .Net libere estas conexiones. Ambos implican bajar al nivel de ServicePoint y tratar con grupos de conexión.

  1. CloseConnectionGroups

    Cuando crea su HTTPWebRequest, puede darle un grupo de conexión. Desde allí, puede usar la función CloseConnectionGroup () desde ServicePoint para eliminar todas las conexiones a ese servicio.

    ServicePoint srvrPoint = ServicePointManager.FindServicePoint(serverUri); srvrPoint.CloseConnectionGroup(myConnGroup)

    Por supuesto, si tiene más de un grupo de conexión, deberá hacerlo en un bucle para cada grupo de conexión.

    Tenga en cuenta que si elige esta ruta, tenga cuidado de no poner todas las conexiones en el mismo grupo. Esto podría hacer que se quede sin enchufes. Más información aquí .

  2. ReleaseAllConnectionGroups

    Hay una función interna dentro de la clase ServicePoint a la que puede llamar que matará todas las conexiones al punto de servicio dado (es decir, el servidor). Sin embargo, como es interno a la clase, tendrás que usar el reflejo para lograrlo:

    ServicePoint srvrPoint = ServicePointManager.FindServicePoint(serverUri); MethodInfo ReleaseConns = srvrPoint.GetType().GetMethod ("ReleaseAllConnectionGroups", BindingFlags.Instance | BindingFlags.NonPublic); ReleaseConns.Invoke(srvrPoint, null);

    Este código simplemente saca los ReleaseAllConnectionGroups de ese ServerPoint y lo invoca sin parámetros. Esta función pasará por todos los grupos de conexión en su lista interna y liberará todos esos recursos, eliminando todas las conexiones.

    Caída: Debido a que este es un miembro privado, no se garantiza que estará allí si actualiza su versión de .Net. Sin embargo, actualmente está disponible en las versiones 2.0 a 4.5. Un enlace al código de ingeniería inversa de ReleaseAllConnectionGroups .

Como no puede establecer el grupo de conexión , deberá usar la opción 2.

Desafortunadamente, no hay otra manera de hacer que .Net cierre esas conexiones de bajo nivel y libere su estado KeepAlive sin configurar el indicador KeepAlive.


¿Por qué no usar el siguiente código?

SqlConnection.ClearAllPools ();

Lo uso en todas mis aplicaciones.