WCF:System.Net.SocketException - 每个套接字地址(协议/网络地址/端口)通常只允许使用一次

Posted

技术标签:

【中文标题】WCF:System.Net.SocketException - 每个套接字地址(协议/网络地址/端口)通常只允许使用一次【英文标题】:WCF: System.Net.SocketException - Only one usage of each socket address (protocol/network address/port) is normally permitted 【发布时间】:2010-11-23 06:33:52 【问题描述】:

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

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

我无法在我们的开发/质量保证环境中重现此行为。我已确保客户端连接在 try..catch..finally 块中关闭。仍然不明白是什么导致了这个问题.. 有人知道吗?

注意:我看过这个SO question,但似乎没有回答我的问题,所以不是重复问题。

【问题讨论】:

是因为 Web 服务使用的是 IIS 正在使用的端口 80?您的服务在生产中使用哪个端口?哪个端口,在生产中配置了 IIS? 两个应用程序的 80 相同。 WCF 服务配置为托管站点的根目录内的虚拟目录。那么,您是说网页请求和尝试使用相同端口的网页服务请求之间可能偶尔会发生冲突? 我也遇到过类似的情况。计划在 wcf 服务中使用 net tcp 端口共享功能。 msdn.microsoft.com/en-us/library/ms734772.aspx如果可行,请告诉我 【参考方案1】:

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

通常,WCF 试图通过池化连接和类似的东西来避免这个问题。这通常是不通过 Internet 的内部服务的情况。我不确定是否有任何 wsHttp 绑定支持连接池,但 netTcp 绑定应该。我会假设命名管道不会遇到这个问题。我不能说 MSMQ 绑定。

您可以使用两种解决方案来解决此问题。您可以增加动态端口范围,也可以减少 TIME_WAIT 的周期。前者可能是更安全的路线,但如果您正在消耗大量的套接字(这听起来不像您的场景的情况),减少 TIME_WAIT 是一个更好的选择(或两者一起使用。)

更改动态端口范围

    打开注册表。 打开密钥 HKLM\System\CurrentControlSet\Services\Tcpip\Parameters 编辑(或创建为 DWORD)MaxUserPort 值。 将其设置为更高的数字。 (即 65534)

更改 TIME_WAIT 延迟

    打开注册表。 打开密钥 HKLM\System\CurrentControlSet\Services\Tcpip\Parameters 编辑(或创建为 DWORD)TcpTimedWaitDelay。 将其设置为较小的数字。值以秒为单位。 (即延迟 1 分钟为 60)

上述解决方案之一应该可以解决您的问题。如果它在更改端口范围后仍然存在,我会尝试增加轮询的周期,以减少它发生的频率……这将为您提供更多的回旋余地来解决时间等待延迟。作为最后的手段,我会更改时间等待延迟。

【讨论】:

Uhm... 这个链接msdn.microsoft.com/en-us/library/aa560610(v=bts.20).aspx 对参数 TCPTimeWaitDelay 的拼写不同。它拼写为 TcpTimedWaitDelay。我怎样才能确认它是什么?来自 technet 的更多信息:technet.microsoft.com/en-us/library/cc938217.aspx TcpTimeWaitDelay 的大小写是否正确?如果是这样,我会修复答案。 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpTimedWaitDelay 是否有一个计数器可以让我查看当前正在使用的连接数? 根据@Jaans 引用的MSDN 文章,TcpTimedWaitDelay 的范围为30 到300,默认为240。单位为秒,jrista 状态。【参考方案2】:

HttpClient,虽然它实现了 IDisposable 是一个共享对象,但你应该尽可能减少实例的数量。您可以在应用程序的整个生命周期中只使用一个实例,而不是为每个请求创建一个实例。

我在http://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ 上写了很多关于它的文章

【讨论】:

以上是关于WCF:System.Net.SocketException - 每个套接字地址(协议/网络地址/端口)通常只允许使用一次的主要内容,如果未能解决你的问题,请参考以下文章

WCF学习大全

WCF 服务、WCF RIA 服务和 WCF 数据服务之间的区别

WCF / WCF 数据服务 / WCF RIA 服务

无废话WCF系列教程 -- 李林峰

WCF 一步一步 发布 WCF服务 到 IIS (图)

WCF入门教程三[WCF的宿主]