Please don't close as duplicate until you read the question to the end; I already googled for hours without success.
EDIT: Now I'm convinced it's related to the way WCF caches opened TCP connections (connection pooling). Please take a look at edit #5 at the end of he question.
I basically have a WCF service that uses a netTcpBinding
configuration. Even if I close the client proxy gracefully (see code below), server always logs "System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host
".
I've narrowed down the issue to the most basic WCF example I could write. I'm getting the exception in the logs produced by WCF tracing every-time I close the client application. I'm not getting any exception in my own code though, which means it works as expected and I can't debug anything to see what's going wrong for WCF to add an error in my logs.
Service interface/implementation:
[ServiceContract]
public interface IService1
{
[OperationContract]
string DoWork();
}
...
public class Service1 : IService1
{
public string DoWork()
{
return "12";
}
}
Server-side configuration:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="WebApplication1.Service1">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="netTcpEndpointBinding" contract="WebApplication1.IService1" />
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="netTcpEndpointBinding">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
</configuration>
Client-side configuration:
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IService1">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost/WebApplication1/Service1.svc"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IService1"
contract="ServiceReference1.IService1" name="NetTcpBinding_IService1" />
</client>
</system.serviceModel>
</configuration>
Client-side code that consumes the service (VS2012 generated the client proxy for me using "Add service reference"):
private async Task<string> TestTask()
{
Service1Client proxy = null;
try
{
Console.WriteLine("Calling service");
proxy = new Service1Client();
return await proxy.DoWorkAsync();
}
finally
{
if (proxy.State != System.ServiceModel.CommunicationState.Faulted)
{
Console.WriteLine("Closing client");
proxy.Close();
}
else
{
Console.WriteLine("Aborting client");
proxy.Abort();
}
}
}
Everything works fine:
Calling service
Closing client
12
But as soon as the application terminates, the server logs an exception. I understand I shouldn't be worried about this exception because it works as expected (exception only appears in logs) and could happen anyway in case the client is terminated abruptly before calling .Close()
/.Abort()
.
But still, is this a normal behavior? I mean, if I correctly closes my client proxy, I expect the server to not log an exception (that is polluting my logs). I also assume some TCP connection is still established between the client and the server (unknown state) after closing the client proxy, because the server only logs the exception after the whole client application terminates. If such a connection is still opened, can't this introduce unexpected behavior (such as max number of connected clients)? Is this really expected?
I found different threads about the issue:
wcf "An existing connection was forcibly closed by the remote host" after closing client
The conclusion would be "don't care about it".
Could someone confirm that with some references and explain why this exception is thrown anyway?
EDIT:
Log trace of the exception:
<Exception>
<ExceptionType>System.Net.Sockets.SocketException, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>An existing connection was forcibly closed by the remote host</Message>
<StackTrace>
à System.ServiceModel.Channels.SocketConnection.HandleReceiveAsyncCompleted()
à System.ServiceModel.Channels.SocketConnection.OnReceiveAsync(Object sender, SocketAsyncEventArgs eventArgs)
à System.Net.Sockets.SocketAsyncEventArgs.FinishOperationAsyncFailure(SocketError socketError, Int32 bytesTransferred, SocketFlags flags)
à System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
à System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host</ExceptionString>
<NativeErrorCode>2746</NativeErrorCode>
</Exception>
Thanks a lot
EDIT 2: I have the same problem when hosting the service in IIS or when it's self-hosted in a Windows service
EDIT 3: here's a full example to reproduce the issue: http://speedy.sh/ENB59/wcf-test.zip
EDIT 4:
I tried to monitor what is actually happening under the hood with the TCP connection WCF establishes for me.
After closing the client proxy, I still see an opened TCP connection to my server:
I assume this is related to the TCP connection to be cached for a future re-use (i.e. connection pooling), because opening a new connection to the server (after the first client proxy has been closed) doesn't create a new TCP connection. If I call Console.WriteLine(new Test().TestTask().Result);
twice in my application, I still only see one opened TCP connection.
I also noted this connection dies because of a timeout if I wait too long after closing the client channel.
EDIT 5: OK, I found documentation on MSDN about that connection pooling:
The NetTcpBinding uses TCP connection pooling based on the service’s host DNS name and the port number the service is listening on. This works well when a client makes calls to different services on different ports, or services are hosted in a single process and share a port. If a single client calls multiple services sharing a port that are hosted in different processes, or are WAS/IIS hosted, the client side pooling may lead to problems where a connection to Service A is reused for Service B, resulting in an exception being thrown, the connection aborted, and a new channel created. To avoid this problem, use a CustomBinding and specify a different ConnectionPoolSettings.GroupName for each service the client communicates with.
So now my question would be: if that's a normal behavior, what could I do to prevent my log to be polluted with all those exceptions?
finally
block might be the source of the issue. I'm just putting this out there, since at a reasonable glance I don't see a problem with your code, but if something happened in thetry
block, you may be trying to callClose()
on a channel that is in a bad or faulted state. Granted you set it tonull
in thecatch
block, but what if something funny is going on and it's not a caught exception? – Comminutefinally
block, yes, in case the proxy becomes in a faulted state for any reason after theawait
and before theClose
, it'll certainly throw an exception. – Voltageproxy.Close();
on the client you are telling the server to close the connection by force, so logically server is logging correct exception, or am I missing something here?? – Wabble