2009-05-14 16 views
81

Los RFC "finos" mandato de todos los RFC-cliente que tenga cuidado de no utilizar más de 2 conexiones por host ...¿Cómo puedo eliminar mediante programación el límite de 2 conexión en WebClient

Microsoft implementó esta en WebClient. Sé que se puede apagar con

App.config:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
<system.net> 
    <connectionManagement> 
    <add address="*" maxconnection="100" /> 
    </connectionManagement> 
</system.net> 
</configuration> 

(que se encuentra en http://social.msdn.microsoft.com/forums/en-US/netfxnetcom/thread/1f863f20-09f9-49a5-8eee-17a89b591007)

Pero, ¿cómo puedo hacerlo mediante programación?

accordin a http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.defaultconnectionlimit.aspx

"Cambio de la propiedad DefaultConnectionLimit tiene ningún efecto sobre objetos ServicePoint existente, sino que afecta sólo los objetos ServicePoint que son inicializado después del cambio Si el valor de esta propiedad no ha sido conjunto. ya sea directamente o a través de la configuración, el valor predeterminado es DefaultPersistentConnectionLimit constante. "

Me gustaría configurar mejor el límite cuando instalo WebClient, pero simplemente eliminar esta triste limitación programáticamente al inicio de mi programa estaría bien también.

El servidor al que accedo no es un servidor web normal en Internet, sino bajo mi control y en la LAN local. Deseo hacer llamadas a la API, pero no uso servicios web o remoto

+0

Podría votar esta pregunta si supiera por qué tiene que violar las normas internacionales. –

+15

No es realmente un estándar. El RFC "recomienda" que limite los clientes a dos conexiones, pero en realidad no es un requisito. Lo más probable es que el póster necesite descargar más de 2 artículos a la vez. –

+12

Accedo a una API en mi propio servidor. No quiero dañar a los hosts en internet. – Christian

Respuesta

48

Con algunos consejos de aquí y en otros lugares que logrado solucionar este problema en mi solicitud anulando la clase WebClient que estaba usando:

class AwesomeWebClient : WebClient { 
    protected override WebRequest GetWebRequest(Uri address) { 
     HttpWebRequest req = (HttpWebRequest)base.GetWebRequest(address); 
     req.ServicePoint.ConnectionLimit = 10; 
     return (WebRequest)req; 
    } 
} 
+23

en mi humilde opinión de que configurar 'System.Net.ServicePointManager.DefaultConnectionLimit' es una mejor solución, ya que no puede suponer que' WebRequest' es un ' HttpWebRequest', por ejemplo, podría ser un 'FileRequest'. – Dennis

5

Si encuentra el objeto ServicePoint que utiliza su WebClient, puede cambiar su límite de conexión. Los objetos HttpWebRequest tienen un descriptor de acceso para recuperar el que se construyó para usar, por lo que podría hacerlo de esa manera. Si tiene suerte, todas sus solicitudes podrían terminar compartiendo el mismo ServicePoint, por lo que solo tendría que hacerlo una vez.

No conozco ninguna forma global de cambiar el límite. Si modificó el DefaultConnectionLimit lo suficientemente temprano en la ejecución, probablemente esté bien.

Alternativamente, podría vivir con el límite de conexión, ya que la mayoría del software de servidor lo va a estrangular de todos modos. :)

+0

Este servidor no me estrangulará (de hecho, lo hará, pero de una manera diferente) ya que está completamente bajo mi control – Christian

+1

Un servidor puede acelerarse con muchas conexiones, pero no lo he experimentado incluso con un servidor pequeño (alojado en una máquina virtual limitada). El límite 2 en el lado del cliente me retuvo por otro lado. Aumentar el límite liberó la situación. –

+1

También dudo que ninguno de los navegadores de hoy obedecería al límite de HTTP 1.1 RFC de 2. –

4

Tenemos una situación con respecto a la pieza anterior de la configuración de la aplicación. config

para que esto sea válido en una aplicación de consola, agregamos el System.Configuration reference dll. Sin la referencia, lo anterior fue inútil.

110

para los interesados:

System.Net.ServicePointManager.DefaultConnectionLimit = x (donde x es el número deseado de conexiones)

sin necesidad de referencias adicionales

acaba de asegurarse de que esto se llama antes de crear el punto de servicio como se ha mencionado arriba en la publicación.

+0

¿Podría esto agregarse a application_start en el global? por lo que afecta a todas las conexiones realizadas? – TheAlbear

+0

¿Cómo y dónde agregar System.Net.ServicePointManager.DefaultConnectionLimit = x? –

+0

Curiosamente, el comentario del código para DefaultConnectionLimit (navegando con F12) dice que su valor predeterminado es Int32.MaxValue. Sin embargo, mediante la inspección de depuración es 2 como se reivindica. – crokusek

6

Esta solución le permite cambiar el límite de conexiones en cualquier momento:

private static void ConfigureServicePoint(Uri uri) 
{ 
    var servicePoint = ServicePointManager.FindServicePoint(uri); 

    // Increase the number of TCP connections from the default (2) 
    servicePoint.ConnectionLimit = 40; 
} 

La primera vez que alguien llama a esto FindServicePoint, se crea una instancia de ServicePoint y una WeakReference se crea para aferrarse a ella en el interior el ServicePointManager. Las solicitudes posteriores al gerente para el mismo Uri devuelven la misma instancia. Si la conexión no se usa después, el GC lo limpia.

+1

El único problema con FindServicePoint es que le devuelve un ServicePoint pero no sabe si será el mismo ServicePoint que obtiene su cliente. – jeffa00

+2

Eso no es un "problema", es solo una parte normal del trabajo. Como con todas las soluciones, debes encontrar una manera de probar eso. Mi manera era establecer la configuración en .config a "1", observar el rendimiento terrible y configurarlo en el código (como aquí), observando el rendimiento mejorado. – Abacus

+0

El 'ServicePoint' se pierde (junto con su configuración) después de' MaxIdleTime' –

Cuestiones relacionadas