Bei Verwendung der ConnectionGroupName-Eigenschaft der System.Net.HttpWebRequest-Klasse der .NET Framework 2.0 oder 4.0 sind möglicherweise keine verfügbaren Ports verfügbar.
Dieser Artikel hilft Ihnen, das Problem zu beheben, bei dem bei Verwendung der ConnectionGroupName Eigenschaft der Klasse in Microsoft .NET Framework 2.0 oder 4.0 möglicherweise nicht mehr verfügbare Ports verfügbar System.Net.HttpWebRequest sind.
Ursprüngliche Produktversion: Microsoft .NET Framework 2.0, 4.0
Ursprüngliche KB-Nummer: 2551125
Problembeschreibung
Sie verwenden die System.Net.HttpWebRequest Klasse in Ihrer Anwendung basierend auf dem .NET Framework 2.0 oder 4.0. Bei der HTTP-Anforderung legen Sie die ConnectionGroupName Eigenschaft der Klasse bei jeder Verwendung der Klasse auf einen eindeutigen Namen fest.
Wenn Sie immer wieder Anforderungen an den GLEICHEN Server senden, wobei ein eindeutiger ConnectionGroupName Wert für die ausgehenden Anforderungen festgelegt wird, und Sie nicht zulassen, dass das zugrunde liegende System.Net.ServicePoint Objekt, das den Anforderungen zugeordnet ist, während der zulässigen Leerlaufzeit im Leerlauf bleibt, werden Sie feststellen, dass die Portnutzung aus Ihrer Anwendung ständig wächst und nie abnimmt.
Dies führt dazu, dass das zugrunde liegende System.Net.ServicePoint Objekt, das dem objekt zugeordnet HttpWebRequest ist, eindeutige (n) erstellt und für jedes dieser Objekte ConnectionGroup ein neues erstellt System.Net.Connection ConnectionGroup wird. Diese zugrunde liegenden System.Net.Connection Objekte sind jeweils einem eindeutigen Winsock-Sockethandleverweis zugeordnet, der im Prozess geöffnet bleibt, bis dem Objekt die Möglichkeit gegeben System.Net.ServicePoint wird, für einen begrenzten Zeitraum im Leerlauf zu bleiben. Der Standardwert dieser Zeit beträgt 100 Sekunden und wird von der ServicePointManager.MaxServicePointIdleTime Eigenschaft gesteuert.
Wenn das ServicePoint Objekt nie im Leerlauf gehalten wird und ständig neue ConnectionGroup (s) und damit ein zugrunde liegendes Objekt erstellt System.Net.Connection wird, werden Sie feststellen, dass der verfügbaren Socketspeicher oder die Portnummern der Anwendung bald nicht mehr zur Verfügung stehen. Die sofortige Auswirkung dieses Problems besteht darin, dass die Anwendung keine neuen Objekte mehr erstellen Connection kann und eine Ausnahme ausgelöst wird, die besagt, dass ein Vorgang für einen Socket nicht ausgeführt werden konnte, weil das System nicht über genügend Pufferspeicher verfügte oder weil eine Warteschlange voll war, die dem Winsock-Fehler 10055 = WSAENOBUFS entspricht.
Wenn Sie während dieses Symptoms eine Absturzabbilddatei Ihres Prozesses erfassen, werden viele System.Net.Sockets.Socket Objekte, System.Net.ConnectionGroup Objekte und Objekte in System.Net.Connection der Speicherabbilddatei angezeigt, die nicht vom Garbage Collector bereinigt wurden.
Zum Beispiel:
0:000> !dumpheap -type System.Net.Sockets.Socket -stat
total Sock_Count objects
Statistics:
MT Count TotalSize Class Name
<<MT>> Sock_Count <<Size>> System.Net.Sockets.Socket
Total Sock_Count objects
0:000> !dumpheap -type System.Net.ConnectionGroup -stat
total Group_Count objects
Statistics:
MT Count TotalSize Class Name
<<MT>> Group_Count <<Size>> System.Net.ConnectionGroup
Total Group_Count objects
0:000> !dumpheap -type System.Net.Connection -stat
total Conn_Count objects
Statistics:
MT Count TotalSize Class Name
<<MT>> Conn_Count <<Size>> System.Net.Connection
Total Conn_Count objects
Dabei ist Sock_Count, Group_Count und Conn_Count die Anzahl der Socket Objekte, Objekte bzw. Objekte und in der ConnectionGroup Regel eine große Anzahl in Connection Tausend.
Ursache
Die konstante Verwendung desselben ServicePoint Objekts zum Erstellen ConnectionGroup eindeutiger (n) Objekte lässt nie zu, dass sie ServicePoint im Leerlauf bleiben. Dies führt dazu, dass die ServicePoint zugrunde liegenden Objekte, die länger als die zugeordnete Zeit im Leerlauf waren, nie bereinigt werden können System.Net.Connection (Standardeinstellung 100 Sekunden).
Jede Connection oder reserviert eine lokale Socket Portnummer, und wenn Sie das Systemlimit (Standard 5000) erreichen, können Sie keine zusätzlichen Verbindungen herstellen.
Lösung
Wenn diese Art von Problem auftritt, bei dem aufgrund einer konstanten Erstellung einer eindeutigen Eigenschaft der Klasse viele Objekte angezeigt System.Net.Connection ConnectionGroupName HttpWebRequest werden, wird empfohlen, die Anzahl der ConnectionGroup (n) auf eine begrenzte Anzahl zu beschränken, um zu verhindern, dass keine verfügbaren Ports mehr verfügbar sind. Durch das Begrenzen der Anzahl ConnectionGroup (n) wird sichergestellt, dass die maximale Anzahl geöffneter Elemente Connections eingeschränkt ist und nicht über die verfügbaren Grenzen hinausgeht.
Eine weitere Alternative, um zu verhindern, dass dieses Szenario auftritt, besteht darin, das HTTP-Keep-Alive Verhalten der Klasse zu HttpWebRequest deaktivieren, indem Sie die KeepAlive Eigenschaft auf "false" festlegen. Durch deaktivieren des HTTP-Keep-Alive Verhaltens wird sichergestellt, dass die zugrunde liegende Verbindung geschlossen wird, sobald eine Anforderung gewartet wird, wodurch sichergestellt wird, dass der Socketverweis sofort freigegeben wird. Dies wiederum bereinigt den System.Net.Connection Verweis und ist nicht davon System.Net.Sockets.Socket abhängig, dass der ServicePoint Leerlauftimer abläuft.
Sie können die Funktion auch System.Net.ServicePoint.CloseConnectionGroup in regelmäßigen Abständen von Ihrer Anwendung aufrufen, die alle alten Connection oder Verweise sofort Socket freigibt. Wenn Sie diese Funktion verwenden möchten, gehen Sie folgendermaßen vor:
Sie müssen das Objekt abrufen, das
ServicePointDem aktuellen Webservernamen zugeordnet ist.Nachdem Sie das Objekt abgerufen haben, rufen Sie
ServicePointdie Funktion desCloseConnectionGroupabgerufenen ObjektsServicePointauf, und übergeben Sie die Namen derjenigen, dieConnectionGroupNameSie bisher in Ihrer Anwendung erstellt haben und bereinigt werden müssen.
Sie können den folgenden Code als Beispiel verwenden:
void CloseIdleConnectionGroups(String[] strGroups, String strURL)
{
try
{
System.Net.ServicePoint oSP = System.Net.ServicePointManager.FindServicePoint(new Uri(strURL));
foreach (String strGroup in strGroups)
{
oSP.CloseConnectionGroup(strGroup);
}
}
catch (Exception oEx)
{
// handle the exception
}
}