WCF:System.Net.SocketException - 通常只允许每个套接字地址(协议/网络地址/端口)使用一次
我有一个 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问题,但似乎没有回答我的问题,所以这不是重复的问题。
I have a WCF service and a Web application. Web application makes calls to this WCF service in a continous manner a.k.a polling. In our production environment, I receive this error very rarely. Since, this is an internal activity users were not aware of when this error is thrown.
Could not connect to
http://localhost/QAService/Service.svc.
TCP error code 10048: Only one usage
of each socket address
(protocol/network address/port) is
normally permitted 127.0.0.1:80. --->
System.Net.WebException: Unable to
connect to the remote server --->
System.Net.Sockets.SocketException:
Only one usage of each socket address
(protocol/network address/port) is
normally permitted 127.0.0.1:80
I am having trouble in reproducing this behaviour in our dev/qa environment. I have made sure that the client connection is closed in a try..catch..finally block. Still don't understand what is causing this issue .. any one aware of this?
Note: I've looked at this SO question, but not seems to be answering my problem, so it is not repeated questions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
TCP/IP 堆栈超载。 Windows(我认为实际上所有套接字堆栈)对可以快速打开的套接字数量有限制,因为套接字在正常操作下如何关闭。每当套接字关闭时,它就会进入 TIME_WAIT 状态一段时间(240 秒 IIRC)。每次轮询时,都会消耗一个超出默认动态范围的套接字(我认为大约有 5000 个动态端口,略高于 1024),并且每次轮询结束时,该特定套接字都会进入 TIME_WAIT。如果轮询足够频繁,最终将消耗所有可用端口,这将导致 TCP 错误 10048。
通常,WCF 会尝试通过池化连接等方式来避免此问题。对于不通过互联网传输的内部服务,通常会出现这种情况。我不确定 wsHttp 绑定是否支持连接池,但 netTcp 绑定应该支持。我认为命名管道不会遇到这个问题。我不能说 MSMQ 绑定。
您可以使用两种解决方案来解决此问题。您可以增加动态端口范围,或减少 TIME_WAIT 的周期。前者可能是更安全的路线,但如果您消耗大量套接字(这听起来不像您的场景的情况),减少 TIME_WAIT 是一个更好的选择(或两者一起。)
更改动态端口范围
更改TIME_WAIT延迟
上述解决方案之一应该可以解决您的问题。如果更改端口范围后它仍然存在,我会尝试增加轮询的周期,这样它就不会那么频繁地发生......这将为您提供更多的余地来解决时间等待延迟。作为最后的手段,我会改变时间等待延迟。
You are overloading the TCP/IP stack. Windows (and I think all socket stacks actually) have a limitation on the number of sockets that can be opened in rapid sequence due to how sockets get closed under normal operation. Whenever a socket is closed, it enters the TIME_WAIT state for a certain time (240 seconds IIRC). Each time you poll, a socket is consumed out of the default dynamic range (I think its about 5000 dynamic ports just above 1024), and each time that poll ends, that particular socket goes into TIME_WAIT. If you poll frequently enough, you will eventually consume all of the available ports, which will result in TCP error 10048.
Generally, WCF tries to avoid this problem by pooling connections and things like that. This is usually the case with internal services that are not going over the internet. I am not sure if any of the wsHttp bindings support connection pooling, but the netTcp binding should. I would assume named pipes does not run into this problem. I couldn't say for the MSMQ binding.
There are two solutions you can use to get around this problem. You can either increase the dynamic port range, or reduce the period of TIME_WAIT. The former is probably the safer route, but if you are consuming an extremely high volume of sockets (which doesn't sound like the case for your scenario), reducing TIME_WAIT is a better option (or both together.)
Changing the Dynamic Port Range
Changing the TIME_WAIT delay
One of the above solutions should fix your problem. If it persists after changing the port range, I would see try increasing the period of your polling so it happens less frequently...that will give you more leeway to work around the time wait delay. I would change the time wait delay as a last resort.
HttpClient,虽然它实现了IDisposable,是一个共享对象,但是你应该尽可能减少实例的数量。您可以在应用程序的整个生命周期中只使用一个实例,而不是为每个请求使用一个实例。
我在 http://aspnetmonsters.com/2016/08 上写了很多关于它的文章/2016-08-27-httpclient错误/
HttpClient, although it implements IDisposable is a shared object, you should reduce the number of instances as much as possible. You can get away with only having one instance for the entire lifetime of your application rather than one for each request.
I wrote about it pretty extensively at http://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/