WCF: System.Net.SocketException: normalmente solo se permite un uso de cada dirección de socket (protocolo / dirección de red / puerto).

Tengo un servicio WCF y una aplicación web. La aplicación web realiza llamadas a este servicio de WCF de manera continua, también conocida como sondeo. En nuestro entorno de producción, recibo este error muy raramente. Dado que, esta es una actividad interna que los usuarios no conocían cuando se lanzó este error.

No se pudo conectar a http: //localhost/QAService/Service.svc . Código de error TCP 10048: normalmente solo se permite un uso de cada dirección de socket (protocolo / dirección de red / puerto) 127.0.0.1:80. —> System.Net.WebException: no se puede conectar al servidor remoto —> System.Net.Sockets.SocketException: normalmente solo se permite el uso de cada dirección de socket (protocolo / dirección de red / puerto) 127.0.0.1 : 80

Tengo problemas para reproducir este comportamiento en nuestro entorno dev / qa. Me he asegurado de que la conexión del cliente esté cerrada en un bloque try..catch..finally. Todavía no entiendo qué está causando este problema … ¿alguien al tanto de esto?

Nota : He examinado esta pregunta SO , pero parece que no responde mi problema, por lo que no se trata de preguntas repetidas.

Está sobrecargando la stack de TCP / IP. Windows (y creo que todas las stacks de tomas en realidad) tienen una limitación en el número de tomas que se pueden abrir en secuencia rápida debido a cómo se cierran las tomas bajo operación normal. Cada vez que se cierra un socket, ingresa al estado TIME_WAIT durante un tiempo determinado (240 segundos IIRC). Cada vez que sondea, un socket se consume fuera del rango dynamic predeterminado (creo que son alrededor de 5000 puertos dynamics justo por encima de 1024), y cada vez que finaliza ese sondeo, ese socket en particular entra en TIME_WAIT. Si realiza una encuesta con la frecuencia suficiente, eventualmente consumirá todos los puertos disponibles, lo que dará como resultado el error TCP 10048.

Generalmente, WCF intenta evitar este problema agrupando conexiones y cosas por el estilo. Este suele ser el caso de los servicios internos que no se transmiten por Internet. No estoy seguro de si alguno de los enlaces wsHttp admite la agrupación de conexiones, pero el enlace netTcp debería. Supongo que las tuberías con nombre no se topan con este problema. No podría decir para el enlace de MSMQ.

Hay dos soluciones que puede usar para evitar este problema. Puede boost el rango del puerto dynamic o reducir el período de TIME_WAIT. La primera es probablemente la ruta más segura, pero si consume un volumen extremadamente alto de sockets (que no suena como en el caso de su escenario), la reducción de TIME_WAIT es una mejor opción (o ambas juntas).

Cambiar el rango de puertos dynamics

  1. Abrir regedit.
  2. Tecla de abrir HKLM \ System \ CurrentControlSet \ Services \ Tcpip \ Parameters
  3. Edite (o cree como DWORD) el valor de MaxUserPort.
  4. Establecerlo en un número más alto. (es decir, 65534)

Cambiar el retraso TIME_WAIT

  1. Abrir regedit.
  2. Tecla de abrir HKLM \ System \ CurrentControlSet \ Services \ Tcpip \ Parameters
  3. Edite (o cree como DWORD) el TcpTimedWaitDelay.
  4. Establecerlo en un número inferior. El valor está en segundos. (es decir, 60 para 1 minuto de retraso)

Una de las soluciones anteriores debería solucionar su problema. Si persiste después de cambiar el rango del puerto, vería intentar boost el período de su votación para que ocurra con menos frecuencia … eso le dará más libertad de acción para evitar el retraso de espera. Cambiaría el tiempo de demora de espera como último recurso.

HttpClient, aunque implementa IDisposable es un objeto compartido, debe reducir el número de instancias tanto como sea posible. Puede salirse con la suya teniendo solo una instancia durante toda la vida de su aplicación en lugar de una para cada solicitud.

Escribí bastante extensamente en http://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/