Hoping someone can give me a clue on this because I'm pretty stuck
A bit of background that may or may not be relevant: I have 2 applications, AC and XV. AC acts as a "controller" for multiple instances of XV. Each instance of XV will act as a server to AC which can then send instructions, ask for progress and results etc.
The process of starting up each instance of XV is as follows:-
- AC starts a self hosted WCF service (the "PortCallBackService"). It uses TCP, localhost and a port of 0 along with the ListenURIMode of zero to get Windows to assign an available port. (It sets this up once for all instances of XV, not once for each)
- AC starts a XV as a Process and passes the port from step 1 as a parameter
- XV starts up a Self hosted WCF service. It uses TCP, localhost and a port of 0 along with the ListenURIMode of zero to get Windows to assign an available port (N.b. it has a different path to the callback service). Further, this service is stateful so it actually starts the service then creates a sessionbound factory which it uses to spen a service.
- XV then reports the port it generated in step 3 back to AC so AC knows what port to communicate with it on. AC records this for each instance of XV.
That's the context and might, hopefully, provide some sort of clue.
The problem I'm getting is that, sometimes and apparently at random, XV fails to open it's service host in step 3 and throws an error: "A TCP error (10013: An attempt was made to access a socket in a way forbidden by its access permissions) occurred while listening on IP Endpoint=0.0.0.0:62388" (unsurprisingly that port number changes each time)
Trouble is that error message is pretty generic and I'm not sure why it is being refused. It happens maybe one time in a hundred and I haven't been able to determine any pattern to this. I'm looking for suggestions on how to investigate further.
The code of the routine that opens the service is:-
//Start the AquatorXV service
Uri baseAddress = new Uri("net.tcp://localhost:0/AquatorXVService");
ServiceHost host = new ServiceHost(typeof(AquatorXV.Server.AquatorXVServiceInstance), baseAddress);
NetTcpBinding endPointBinding = new NetTcpBinding()
{
MaxReceivedMessageSize = 2147483647,
MaxBufferSize = 2147483647,
MaxBufferPoolSize = 2147483647,
SendTimeout = TimeSpan.MaxValue,
OpenTimeout = new TimeSpan(0, 0, 20)
};
ServiceEndpoint endPoint = host.AddServiceEndpoint(typeof(AquatorXVServiceInterface.IAquatorXVServiceInstance), endPointBinding, baseAddress);
endPoint.ListenUriMode = ListenUriMode.Unique;
ServiceMetadataBehavior metadataBehaviour = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (metadataBehaviour == null)
{
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
}
else
{
metadataBehaviour.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
}
ServiceDebugBehavior debugBehaviour = host.Description.Behaviors.Find<ServiceDebugBehavior>();
if (debugBehaviour == null)
host.Description.Behaviors.Add( new ServiceDebugBehavior() { IncludeExceptionDetailInFaults = true });
else if (!debugBehaviour.IncludeExceptionDetailInFaults)
debugBehaviour.IncludeExceptionDetailInFaults = true;
ServiceBehaviorAttribute behaviourAttribute = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
if (behaviourAttribute == null)
host.Description.Behaviors.Add(new ServiceBehaviorAttribute { AddressFilterMode = AddressFilterMode.Any });
else
behaviourAttribute.AddressFilterMode = AddressFilterMode.Any;
host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
try
{
host.Open(); //<<<<<<This the the line that throws the exception
}
catch (Exception ex)
{
App.WriteToTestLog(ex.Message);
App.WriteToTestLog(ex.StackTrace);
throw;
}
int port = host.ChannelDispatchers.First().Listener.Uri.Port;
//Start the session bound factory service
Uri sessionBoundFactoryBaseAddress = new Uri("net.tcp://localhost:" + port.ToString() + "/AquatorXVSessionBoundFactoryService");
ServiceHost sessionBoundFactoryHost = new ServiceHost(typeof(AquatorXV.Server.SessionBoundFactory), sessionBoundFactoryBaseAddress);
ServiceMetadataBehavior smbFactory = new ServiceMetadataBehavior();
smbFactory.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
sessionBoundFactoryHost.Description.Behaviors.Add(smbFactory);
sessionBoundFactoryHost.AddServiceEndpoint(typeof(AquatorXVServiceInterface.ISessionBoundFactory), new NetTcpBinding(), sessionBoundFactoryBaseAddress);
sessionBoundFactoryHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
sessionBoundFactoryHost.Open();
The full call stack of the exception is:-
Unhandled Exception: System.ServiceModel.CommunicationException: A TCP error (10013: An attempt was made to access a socket in a way forbidden by its access permissions) occurred while listening on IP Endpoint=0.0.0.0:50124. ---> System.Net.Sockets.SocketException: An attempt was made to access a socket in a way forbidden by its access permissions
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Bind(EndPoint localEP)
at System.ServiceModel.Channels.TcpChannelListener.ListenAndBind(IPEndPoint localEndpoint)
--- End of inner exception stack trace ---
at System.ServiceModel.Channels.TcpChannelListener.ListenAndBind(IPEndPoint localEndpoint)
at System.ServiceModel.Channels.TcpChannelListener.SetupUniquePort(BindingContext context)
at System.ServiceModel.Channels.TcpChannelListener..ctor(TcpTransportBindingElement bindingElement, BindingContext context)
at System.ServiceModel.Channels.TcpTransportBindingElement.BuildChannelListener[TChannel](BindingContext context)
at System.ServiceModel.Channels.Binding.BuildChannelListener[TChannel](Uri listenUriBaseAddress, String listenUriRelativeAddress, ListenUriMode listenUriMode, BindingParameterCollection parameters)
at System.ServiceModel.Description.DispatcherBuilder.MaybeCreateListener(Boolean actuallyCreate, Type[] supportedChannels, Binding binding, BindingParameterCollection parameters, Uri listenUriBaseAddress, String listenUriRelativeAddress, ListenUriMode listenUriMode, ServiceThrottle throttle, IChannelListener& result, Boolean supportContextSession)
at System.ServiceModel.Description.DispatcherBuilder.BuildChannelListener(StuffPerListenUriInfo stuff, ServiceHostBase serviceHost, Uri listenUri, ListenUriMode listenUriMode, Boolean supportContextSession, IChannelListener& result)
at System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost)
at System.ServiceModel.ServiceHostBase.InitializeRuntime()
at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at AquatorXV.AquatorControl.StartRemoteServerWCF(Int32 applicationInstanceId, Int32 machineServiceCallBackServicePort)
at AquatorXV.App.Main(String[] args)
I've looked in the event viewer and I've found the following event reported
Application: AquatorXV.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.Net.Sockets.SocketException at System.Net.Sockets.Socket.DoBind(System.Net.EndPoint, System.Net.SocketAddress) at System.Net.Sockets.Socket.Bind(System.Net.EndPoint) at System.ServiceModel.Channels.TcpChannelListener.ListenAndBind(System.Net.IPEndPoint) Exception Info: System.ServiceModel.CommunicationException at System.ServiceModel.Channels.TcpChannelListener.ListenAndBind(System.Net.IPEndPoint) at System.ServiceModel.Channels.TcpChannelListener.SetupUniquePort(System.ServiceModel.Channels.BindingContext) at System.ServiceModel.Channels.TcpChannelListener..ctor(System.ServiceModel.Channels.TcpTransportBindingElement, System.ServiceModel.Channels.BindingContext) at System.ServiceModel.Channels.TcpTransportBindingElement.BuildChannelListener[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](System.ServiceModel.Channels.BindingContext) at System.ServiceModel.Channels.Binding.BuildChannelListener[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](System.Uri, System.String, System.ServiceModel.Description.ListenUriMode, System.ServiceModel.Channels.BindingParameterCollection) at System.ServiceModel.Description.DispatcherBuilder.MaybeCreateListener(Boolean, System.Type[], System.ServiceModel.Channels.Binding, System.ServiceModel.Channels.BindingParameterCollection, System.Uri, System.String, System.ServiceModel.Description.ListenUriMode, System.ServiceModel.Dispatcher.ServiceThrottle, System.ServiceModel.Channels.IChannelListener ByRef, Boolean) at System.ServiceModel.Description.DispatcherBuilder.BuildChannelListener(StuffPerListenUriInfo, System.ServiceModel.ServiceHostBase, System.Uri, System.ServiceModel.Description.ListenUriMode, Boolean, System.ServiceModel.Channels.IChannelListener ByRef) at System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(System.ServiceModel.Description.ServiceDescription, System.ServiceModel.ServiceHostBase) at System.ServiceModel.ServiceHostBase.InitializeRuntime() at System.ServiceModel.ServiceHostBase.OnOpen(System.TimeSpan) at System.ServiceModel.Channels.CommunicationObject.Open(System.TimeSpan) at AquatorXV.AquatorControl.StartRemoteServerWCF(Int32, Int32) at AquatorXV.App.Main(System.String[])