.NET Framework Bookmark and Share   
 index > Network Class Library (System.Net) > WebService call resulting in SocketException
 

WebService call resulting in SocketException

I am calling a webservice on another machine usually about 1-5 times during the execution of an asp.net page (from VB.net) This works well in DEV and I am not able to reliably reproduce in our live environment but throughout the day I get the following exception :

Method Exception ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted WWW.XXX.YYY.ZZZ
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress) at System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP) at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Int32 timeout, Exception& exception) --- End of inner exception stack trace --- at System.Net.HttpWebRequest.GetRequestStream() at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters) at blah blah blah...

I have exhausted google & bing - I think - I have tried implementing a fix I found on the internet, where I'm extending the default webservice proxy with the following :
this didn't work

I've also tried increasing MaxUserPort and TcpTimedWaitDelay in the registry, but it doesn't seem like it has helped.

Can anyone help me? I don't really understand this problem. I figure that this scenario, calling a webservice from a webpage would be a fairly common practice, and that I wouldn't run into errors which look like basic plumbing.

client is asp.net 3.5 / win2k3 r2.
server isas400 / apache tomcat 4

Imports System.Net
Imports System.Net.Sockets
Imports System.Threading
Partial Public Class lookup
    Inherits originalLookup
    Private Shared m_LastBindPortUsed As Integer
    Protected Overrides Function GetWebRequest(ByVal uri As System.Uri) As System.Net.WebRequest
        Dim webreq As HttpWebRequest = CType(MyBase.GetWebRequest(uri), HttpWebRequest)
        webreq.KeepAlive = True
        webreq.ServicePoint.BindIPEndPointDelegate = New BindIPEndPoint(AddressOf BindIPEndPointCallback)
        Return webreq
    End Function
    Public Shared Function BindIPEndPointCallback(ByVal servicePoint As ServicePoint, ByVal remoteEndPoint As IPEndPoint, ByVal retryCount As Integer) As IPEndPoint
        Dim port As Integer = Interlocked.Increment(m_LastBindPortUsed) 'increment
        Interlocked.CompareExchange(m_LastBindPortUsed, 5001, 65534)
        If (remoteEndPoint.AddressFamily = AddressFamily.InterNetwork) Then
                Return New IPEndPoint(IPAddress.Any, port)
        Else
                Return New IPEndPoint(IPAddress.IPv6Any, port)
        End If
    End Function
End Class

  •  
Quinn Wilson
Why are you even binding to a port locally? Looks like you are cycling through the non-reserved port range from 5001-65535. But the question is, why are you doing this?
feroze
--
http://ferozedaud.blogspot.com
http://blogs.msdn.com/feroze_daud
Feroze Daud
Well I don't claim to understand fully, but what I gather from http://blogs.msdn.com/dgorti/archive/2005/09/18/470766.aspx is that when creating a connection to the target machine the webservice client proxy opens a local (client) port for outgoing communication. I understand that in any client communication over tcp-ip we have to bind a client port in a similar fashion, it's just generally hidden from application developers with things like System.Net.WebClient or System.Net.HttpWebRequest. By default it opens a client port in the range, 1024-5000, the code above adds the range 5001-65534 so the client ports are not exhausted as quickly

Quinn Wilson
Ah, I see. If I understand you correctly, you have a three tier application, where the middle-tier (ASP.NET) is making a webservice call out to another server. And the middle-tier is the one that is exhibiting this behavior.

Can you enable tracing on the middle-tier, as described here:http://blogs.msdn.com/feroze_daud/archive/2005/05/12/416922.aspx

and see what the logfile shows?

feroze
--
http://ferozedaud.blogspot.com
http://blogs.msdn.com/feroze_daud
Feroze Daud
hmm, well it's an aspx page which makes calls out to another machine. Two tiers it seems to me.

I enabled the tracing. I have an awful lot of data accumulating, any idea what I should look for?
Quinn Wilson
When you get a repro of the problem, stop tracing. Then, look at the log and try to figure out why the socket is being closed.

Or you can post a snippet of the log here, after removing all personally identifiable information like IP address, etc and we can see if it shows anything.
feroze
--
http://ferozedaud.blogspot.com
http://blogs.msdn.com/feroze_daud
Feroze Daud
thanks for your help by the way,

so, it's odd. I ran with tracing in live environment for a long time before running into this problem ( I think the tracing might introduce a delay sufficient to avoid some kind of race for resources. )

and I wasn't sure what to cut from the log surrounding my error but here's what I've got:

System.Net Verbose: 0 : [2744] WebRequest::Create(http://wpg400a:8080/axis/services/CustGa.CustGaHttpSoap11Endpoint/)
System.Net Verbose: 0 : [2744] HttpWebRequest#40664061::HttpWebRequest(http://wpg400a:8080/axis/services/CustGa.CustGaHttpSoap11Endpoint/#1130302560)
System.Net Verbose: 0 : [2744] Exiting HttpWebRequest#40664061::HttpWebRequest()
System.Net Verbose: 0 : [2744] Exiting WebRequest::Create() -> HttpWebRequest#40664061
System.Net Verbose: 0 : [2744] HttpWebRequest#40664061::GetRequestStream()
System.Net Information: 0 : [2744] Associating HttpWebRequest#40664061 with ServicePoint#45637159
System.Net Information: 0 : [2744] Associating Connection#17943449 with HttpWebRequest#40664061
System.Net.Sockets Verbose: 0 : [2744] Socket#2148853::Socket(InterNetwork#2)
System.Net.Sockets Verbose: 0 : [2744] Exiting Socket#2148853::Socket()
System.Net.Sockets Verbose: 0 : [2744] Socket#2148853::Connect(249:8080#-110661139)
System.Net.Sockets Error: 0 : [2744] Exception in the Socket#2148853::Connect - Only one usage of each socket address (protocol/network address/port) is normally permitted www.xxx.yyy.zzz:8080
System.Net.Sockets Verbose: 0 : [2744] Socket#2148853::Connect(249:8080#-110661139)
System.Net.Sockets Error: 0 : [2744] Exception in the Socket#2148853::Connect - Only one usage of each socket address (protocol/network address/port) is normally permitted www.xxx.yyy.zzz:8080
System.Net.Sockets Verbose: 0 : [2744] Socket#2148853::Dispose()
System.Net Error: 0 : [2744] Exception in the HttpWebRequest#40664061:: - Unable to connect to the remote server
System.Net Error: 0 : [2744] at System.Net.ServicePoint.GetConnection(PooledStream PooledStream, Object owner, Boolean async, IPAddress& address, Socket& abortSocket, Socket& abortSocket6, Int32 timeout)
at System.Net.PooledStream.Activate(Object owningObject, Boolean async, Int32 timeout, GeneralAsyncDelegate asyncCallback)
at System.Net.Connection.CompleteStartConnection(Boolean async, HttpWebRequest httpWebRequest)
System.Net Error: 0 : [2744] Exception in the HttpWebRequest#40664061::EndGetRequestStream - Unable to connect to the remote server
System.Net Error: 0 : [2744] at System.Net.ServicePoint.GetConnection(PooledStream PooledStream, Object owner, Boolean async, IPAddress& address, Socket& abortSocket, Socket& abortSocket6, Int32 timeout)
at System.Net.PooledStream.Activate(Object owningObject, Boolean async, Int32 timeout, GeneralAsyncDelegate asyncCallback)
at System.Net.Connection.CompleteStartConnection(Boolean async, HttpWebRequest httpWebRequest)
Quinn Wilson
So, after this happens, can you do the following command from a command window?

netstat -n -P TCP

and paste the output?

Either your callback code above is not executing in which case it is running out of the 1025-4999 port range, or you are making too many connections and running out of all TCP ports? Hard to say unless we look at the output.

Also, a network sniff using wireshark would help. If the middle-tier is making one connection per webrequest, we could make it use a keep-alive connection if you dont have any security requirements that prevent using a keep-alive connection.
feroze
--
http://ferozedaud.blogspot.com
http://blogs.msdn.com/feroze_daud
Feroze Daud

Unfortunately, that error can mean two different things depending on where its thrown from, which makes finding reliable information about it harder. When thrown from Socket.Bind, it means that you are trying to Bind to a port which is currently in use by another Socket. This is the problem that the workaround with BindIPEndPointDelegate is targetting. But when thrown from Connect, the error means something slightly different.

A TCP connection is really just a mapping from the four-tuple (local address, local port, remote address, remote port) to a particular socket. The operating system uses this mapping to route incoming data to the appropriate socket. When you close a TCP connection, the operating system does not allow you to reopen another connection with the same four-tuple immediately. This time (controlled by TcpTimedWaitDelay) helps ensure that any data from the old connection that arrives after you close the connection gets dropped, and not accidentally routed to a new connection.

Getting this error from Connect means that the Socket was successfully bound to a local port which was in this TCP_TIMEWAIT state, which prevents it from being connected to that specific remote address/port for a short amount of time. This generally only becomes a problem when an application is creating lots of short-lived connections to the same remote address/port. The solution is to reuse connections rather than closing them and creating new ones. Since you are setting HttpWebRequest.KeepAlive to true, its likely the server is closing the connections.

If you cannot get the server to support keep-alive, the only recourse is to retry requests that fail with this error. Eventually the TCP_TIMEWAIT will expire and you will be able to create a new connection.

=dave

Dave Murray [NCL]
I have HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\MaxUserPort set to 25000
and HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpTimedWaitDelay set to 30

So I would need to be using more than 25000 ports in 30 seconds right? I am not getting that kind of traffic.


Quinn Wilson
Are you absolutely sure that the BindIPEndPoint delegate is being invoked?

Can you do a "netstat -n -P TCP" and paste the output when this happens?
feroze
--
My blog
Feroze Daud
I am not sure that the BindIPEndPoint delegate is being invoked, I will add some tracing.

I did a "netstat -n -P TCP" after it occured, and I got around 220 lines just like :

TCP webapp:XXXXX webservice:8080 FIN_WAIT_2

Quinn Wilson
Also, it might help if you attached a code snippet showing how you use this webservice proxy (class named 'lookup' above).

I did a google search for FIN_WAIT_2 and found some pages listing issues with Apache. Basically, it said that some buggy clients were not tearing down the connection when Apache initiated a Fin-Ack-Fin TCP teardown. This resulted in connections left open in FIN_WAIT_2 state on the server.

However, your problem is that these connections are being left open on the client. Is it possible that you are not disposing of the webrequest proxy?
feroze
--
My blog
Feroze Daud

You can use google to search for other answers

Custom Search

More Threads

• System lacked sufficient buffer space? Or a queue was full?
• Efficient way to connect to a website
• HTTPWebRequest on IIS with Integrated Windows Authentication
• HttpListener
• Finding occasional and irregular bad bytes in a reliable(?) networkstream
• FTP file size
• Fetching actual Client IPAddress with Proxy enabled using ASP.NET
• SMTP Host Credentials from web.config
• Downloading file
• ftpwebrequest when to use passive and timeout