WCF:System.Net.SocketException – 通常只允许使用每个套接字地址(协议/networking地址/端口)

我有一个WCF服务和一个Web应用程序。 Web应用程序以连续方式(即轮询)调用此WCF服务。 在我们的生产环境中,我很less收到这个错误。 因为,这是一个内部活动,用户不知道何时抛出这个错误。

无法连接到http://localhost/QAService/Service.svc 。 TCP错误代码10048:每个套接字地址(协议/networking地址/端口)通常只允许使用一个127.0.0.1:80。 —> System.Net.WebException:无法连接到远程服务器—> System.Net.Sockets.SocketException:通常只允许使用每个套接字地址(协议/networking地址/端口)127.0.0.1 :80

我在dev / qa环境中重现这种行为时遇到了麻烦。 我已经确保客户端连接在try..catch..finally块中closures。 仍然不明白是什么导致这个问题..任何人意识到这一点?

:我已经看过这个问题 ,但似乎没有回答我的问题,所以它不是重复的问题。

您正在超载TCP / IP堆栈。 Windows(我认为实际上所有的套接字堆栈)都有一个套接字数量的限制,因为套接字在正常操作下如何closures,可以快速打开。 只要套接字closures,就会进入TIME_WAIT状态一段时间(240秒IIRC)。 每次轮询时,一个套接字会被超出默认的dynamic范围(我认为它的大约是1024个以上的大约5000个dynamic端口),每次轮询结束时,这个特定的套接字就会进入TIME_WAIT。 如果你频繁轮询,你最终将消耗所有可用的端口,这将导致TCP错误10048。

一般来说,WCF通过汇集连接和类似的东西来避免这个问题。 内部服务通常是不通过互联网的情况。 我不知道是否有任何wsHttp绑定支持连接池,但netTcp绑定应该。 我会假设命名pipe道不会遇到这个问题。 我不能说MSMQ绑定。

有两种解决scheme可以用来解决这个问题。 您可以增加dynamic端口范围,也可以减lessTIME_WAIT的时间。 前者可能是更安全的路线,但是如果你正在消耗大量的套接字(这听起来不像你的情况),减lessTIME_WAIT是一个更好的select(或者两者兼而有之)。

更改dynamic端口范围

  1. 打开regedit。
  2. 打开密钥HKLM \ System \ CurrentControlSet \ Services \ Tcpip \ Parameters
  3. 编辑(或创build为DWORD)MaxUserPort值。
  4. 将其设置为更高的数字。 (即65534)

改变TIME_WAIT延迟

  1. 打开regedit。
  2. 打开密钥HKLM \ System \ CurrentControlSet \ Services \ Tcpip \ Parameters
  3. 编辑(或创build为DWORD)的TcpTimedWaitDelay。
  4. 将其设置为较低的数字。 价值以秒为单位。 (即60分钟延迟1分钟)

上述解决scheme之一应该解决您的问题。 如果在更改端口范围后仍然存在,我会看到尝试增加轮询的周期,以免发生这种情况,这会给您更多的时间来解决等待延迟的问题。 我会改变时间等待延迟作为最后的手段。

HttpClient,尽pipe它实现的IDisposable是一个共享对象,你应该尽可能的减less实例的数量。 在应用程序的整个生命周期中,您只能拥有一个实例,而不是每个请求都有一个实例。

我在http://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/上写了相当广泛的文章;