You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WCF自托管服务启动随机报Socket权限错误(10013)排查问询

WCF服务启动随机报Socket 10013错误的排查思路

背景信息

我有AC和XV两个应用,AC作为多个XV实例的控制器,每个XV实例作为服务器供AC发送指令、查询进度与结果。XV实例启动流程如下:

  • AC启动自托管WCF服务(PortCallBackService),采用TCP、localhost、端口0及ListenURIMode.Unique让Windows分配可用端口(为所有XV实例统一配置一次);
  • AC启动XV进程并传入上述端口作为参数;
  • XV启动自托管WCF服务,同样采用TCP、localhost、端口0及ListenURIMode.Unique获取Windows分配的可用端口(路径与回调服务不同),该服务为有状态服务,启动后创建sessionbound factory;
  • XV将生成的端口报告给AC,AC记录每个XV实例的对应端口。

问题现象

XV在启动服务宿主时会随机失败(约百次出现一次),抛出错误:

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:xxxx

端口号每次不同,错误信息无明确指向,无明显规律。

相关代码

//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();

异常调用堆栈

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)

事件查看器日志

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[]) 

排查建议

1. 排查端口TIME_WAIT状态冲突

Windows会把关闭的Socket保留在TIME_WAIT状态一段时间(默认240秒),短时间内频繁启动XV可能导致系统分配到这类端口:

  • 报错时立刻执行netstat -ano | findstr :xxxx(替换xxxx为报错端口),查看该端口是否处于TIME_WAIT状态;
  • 调整TCP参数:修改注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters下的TcpTimedWaitDelay(设为30-60秒),或者扩大动态端口范围(netsh int ipv4 set dynamicport tcp start=49152 num=16384)。

2. 检查权限与安全拦截

  • 尝试用管理员权限运行XV,确认是否是普通用户权限不足导致绑定失败;
  • 临时关闭防火墙/安全软件,测试是否还会出现错误;
  • 检查Windows动态端口范围是否足够:执行netsh int ipv4 show dynamicport tcp查看,若范围过小可扩大。

3. 排查WCF服务初始化的竞态问题

代码中主服务启动后立刻在同一端口启动sessionBoundFactory服务,虽理论上路径不同不冲突,但可尝试:

  • 在host.Open()后添加短暂延迟(比如Thread.Sleep(100))再启动子服务;
  • 检查是否有其他线程在操作该端口资源。

4. 调整Socket绑定地址

当前用0.0.0.0监听所有网卡,可能存在网卡异常导致绑定失败:

  • 把地址改成127.0.0.1而非localhost,强制只监听本地回环;
  • 尝试指定具体物理网卡的IP地址,排除虚拟网卡/VPN的干扰。

5. 检查进程资源泄漏

若XV退出时未正确释放ServiceHost,会导致Socket资源无法回收:

  • 在XV退出逻辑中添加host.Close()和sessionBoundFactoryHost.Close(),最好放在finally块中确保执行;
  • 用任务管理器查看XV进程退出后是否还有残留的WCF相关线程。

6. 增强错误日志

在catch块中添加更多上下文信息,方便定位:

  • 执行netstat -ano并将输出写入日志;
  • 记录当前进程的用户权限、系统动态端口范围等信息。

内容的提问来源于stack exchange,提问作者FunkyDexter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 18:02:02