Come posso rimuovere a livello di codice il limite di 2 connessioni in WebClient


88

Quelle RFC "buone" impongono a ogni client RFC di fare attenzione a non utilizzare più di 2 connessioni per host ...

Microsoft lo ha implementato in WebClient. So che può essere disattivato con

App.config:

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

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

Ma come posso farlo a livello di programmazione?

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

"La modifica della proprietà DefaultConnectionLimit non ha effetto sugli oggetti ServicePoint esistenti; influisce solo sugli oggetti ServicePoint inizializzati dopo la modifica. Se il valore di questa proprietà non è stato impostato direttamente o tramite la configurazione, il valore predefinito è DefaultPersistentConnectionLimit."

Mi piacerebbe configurare meglio il limite quando instanzio il WebClient, ma anche solo rimuovere questa triste limitazione a livello di programmazione all'inizio del mio programma andrebbe bene.

Il server a cui accedo non è un normale server web in Internet, ma sotto il mio controllo e nella LAN locale. Voglio fare chiamate API, ma non uso servizi web o servizi remoti


15
Non è davvero uno standard. La RFC "consiglia" di limitare i client a due connessioni, ma non è realmente un requisito. Molto probabilmente, il poster deve scaricare più di 2 elementi contemporaneamente.
Erik Funkenbusch

12
Accedo a un'API sul mio server. Non voglio danneggiare gli host su Internet.
Christian

12
Ho aumentato il limite di connessione per creare uno strumento di test di carico. È davvero difficile eseguire il test di carico con 2 connessioni misurate. Sono sicuro che ci sono molti motivi per non navigare per utilizzare molte connessioni.
ScottS

1
A proposito, la configurazione sopra interesserà tutte le connessioni controllate da .Net, non solo il client web.
ScottS

2
Perché più di due? Giriamo intorno alla domanda: perché non potevo inviare più di due richieste a un server contemporaneamente in modo asincrono? 2 è solo letteralmente una limitazione.
Csaba Toth

Risposte:


50

Con alcuni suggerimenti da qui e altrove sono riuscito a risolvere questo problema nella mia applicazione sovrascrivendo la classe WebClient che stavo usando:

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

28
IMHO che l'impostazione di System.Net.ServicePointManager.DefaultConnectionLimitè una soluzione migliore, in quanto non si può presumere che WebRequestsia a HttpWebRequest, ad esempio, potrebbe essere a FileRequest.
Dennis

120

per chi è interessato:

System.Net.ServicePointManager.DefaultConnectionLimit = x (dove x è il numero di connessioni desiderato)

non c'è bisogno di riferimenti extra

assicurati solo che venga chiamato PRIMA che il punto di servizio venga creato come menzionato sopra nel post.


Quindi potrebbe essere aggiunto a application_start nel globale? quindi influisce su tutti i collegamenti effettuati?
TheAlbear

Come e dove aggiungere System.Net.ServicePointManager.DefaultConnectionLimit = x?
Arul Sidthan

Stranamente, il commento sul codice per DefaultConnectionLimit (navigazione utilizzando F12) dice che il suo valore predefinito è Int32.MaxValue. Tuttavia dall'ispezione di debug è 2 come affermato.
crokusek

7

Questa soluzione consente di modificare il limite di connessione in qualsiasi 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 prima volta che qualcuno chiama questo FindServicePoint , viene creata un'istanza di ServicePoint e viene creato un WeakReference per conservarlo all'interno del ServicePointManager . Le richieste successive al gestore per lo stesso Uri restituiscono la stessa istanza. Se la connessione non viene utilizzata dopo, il GC la pulisce.


1
L'unico problema con FindServicePoint è che ti restituisce un ServicePoint ma non sai se sarà lo stesso ServicePoint che riceverà il tuo cliente.
jeffa00

2
Non è un "problema", è solo una parte normale del lavoro. Come con tutte le soluzioni, devi trovare un modo per verificarlo. Il mio modo era impostare l'impostazione nel .config su "1", osservare la terribile prestazione e impostarla in codice (come qui), osservando le prestazioni migliorate.
Abacus

1
Il ServicePointsi perde (insieme alle tue impostazioni) dopoMaxIdleTime
Colin Breame

5

Se trovi l'oggetto ServicePoint utilizzato dal tuo WebClient, puoi modificarne il limite di connessione. Gli oggetti HttpWebRequest hanno una funzione di accesso per recuperare quello per cui sono stati progettati, quindi puoi farlo in questo modo. Se sei fortunato, tutte le tue richieste potrebbero finire per condividere lo stesso ServicePoint, quindi dovresti farlo solo una volta.

Non conosco alcun modo globale per cambiare il limite. Se hai modificato il DefaultConnectionLimit abbastanza presto durante l'esecuzione, probabilmente staresti bene.

In alternativa, potresti semplicemente vivere con il limite di connessione, poiché la maggior parte del software del server ti limiterà comunque. :)


Questo server non mi limiterà (in effetti, lo farà, ma in modo diverso) poiché è completamente sotto il mio controllo
Christian

1
Un server potrebbe rallentare con molte connessioni, ma non l'ho sperimentato nemmeno con un piccolo server (ospitato in una VM limitata). D'altra parte, il limite 2 sul lato client mi ha trattenuto. Aumentare il limite ha liberato la situazione.
Csaba Toth

1
Dubito anche che uno qualsiasi dei browser di oggi obbedisca al limite RFC di HTTP 1.1 di 2.
Csaba Toth

4

Abbiamo una situazione riguardante la parte di configurazione di cui sopra in App.Config

Affinché questo sia valido in un'applicazione CONSOLE, abbiamo aggiunto la DLL di riferimento System.Configuration. Senza il riferimento, quanto sopra era inutile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.