You may run out of available ports when using the ConnectionGroupName property of the System.Net.HttpWebRequest class of the .NET Framework 2.0 or 4.0
This article helps you resolve the problem where you might run out of available ports when using the ConnectionGroupName
property of the System.Net.HttpWebRequest
class in Microsoft .NET Framework 2.0 or 4.0.
Original product version: Microsoft .NET Framework 2.0, 4.0
Original KB number: 2551125
Symptoms
You're using the System.Net.HttpWebRequest
class in your application based on the .NET Framework 2.0 or 4.0. When making the HTTP request, you set the ConnectionGroupName
property of the class to a unique name each time you use the class.
If you constantly keep sending requests to the SAME server with a unique ConnectionGroupName
value set on the outgoing requests each time, and you don't allow the underlying System.Net.ServicePoint
object associated with the requests to remain idle for the allowed idle time, you'll notice that the port usage from your application grows constantly and never drops.
This causes the underlying System.Net.ServicePoint
object associated with the HttpWebRequest
to create unique ConnectionGroup
(s) and it ends up creating new System.Net.Connection
for each such ConnectionGroup
. These underlying System.Net.Connection
objects are each associated with a unique winsock socket handle reference that remain open in the process until the System.Net.ServicePoint
object is given a chance to remain idle for a finite amount of time. The default value of this time is 100 seconds and is governed by the ServicePointManager.MaxServicePointIdleTime
property.
If the ServicePoint
object is never kept idle and if it keeps creating new ConnectionGroup
(s) and hence an underlying System.Net.Connection
object, you'll notice that your application will soon run out of available socket space or port numbers. The immediate effect of this issue is that your application will no longer be able to create new Connection
objects and start throwing an exception that says An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full which corresponds with the winsock error 10055 = WSAENOBUFS.
If you capture a hang dump file of your process during this symptom, you'll see many System.Net.Sockets.Socket
objects, System.Net.ConnectionGroup
objects and System.Net.Connection
objects present in the dump file that have not been cleaned up by the garbage collector.
For example:
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
Where Sock_Count, Group_Count and Conn_Count is the count of the Socket
objects, ConnectionGroup
objects and the Connection
objects respectively and will usually be a large number in thousands.
Cause
The constant use of the same ServicePoint
object to create unique ConnectionGroup
(s) never allows the ServicePoint
to remain idle, which causes the ServicePoint
to never get a chance to clean up the underlying System.Net.Connection
objects that have been idle for more than the allocated time (default 100 seconds).
Each Connection
or Socket
reserves a local port number, and when you reach the system limit (default 5000), you won't be able to make additional connections.
Resolution
If you are running into this type of issue where you see many System.Net.Connection
objects because of a constant creation of unique ConnectionGroupName
property of the HttpWebRequest
class, it's recommended that you limit the number of ConnectionGroup
(s) to a limited number to prevent running out of available ports. Limiting the number of ConnectionGroup
(s) will ensure that the maximum number of Connections
that are being opened is restricted and doesn't increase beyond the available bounds.
Another alternative to prevent running into this scenario is to disable the HTTP Keep-Alive behavior of the HttpWebRequest
class by setting the KeepAlive
property to false. Disabling the HTTP Keep-Alive behavior will ensure that the underlying connection is closed once a request is serviced, which ensures that the socket reference is released immediately. This will in turn, clean up the System.Net.Connection
and the System.Net.Sockets.Socket
reference and not be dependent on the ServicePoint
to have its idle timer expire.
You can also call the System.Net.ServicePoint.CloseConnectionGroup
function periodically from your application that will release any old Connection
or Socket
references immediately. To use this function however, you will:
Need to retrieve the
ServicePoint
object associated with your current web server name.Once you retrieve the
ServicePoint
object, call theCloseConnectionGroup
function of the retrievedServicePoint
object and pass the names of whicheverConnectionGroupName
you've created so far in your application and need to be cleaned up.
You can use the following code as an example:
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
}
}
References
Feedback
https://aka.ms/ContentUserFeedback.
Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see:Submit and view feedback for