HttpWebRequest 将套接字保持在 TIME WAIT 状态
我很难弄清楚 .NET 4.0 中的 HttpWebRequest 为每个请求创建一个套接字连接,但之后无法关闭套接字。 当我执行例如 50 个 HttpWebRequests 时,我在 netstat 中看到 50 个处于 WAIT 状态的 TCP 套接字连接。
我已经将代码减少到最少:
Dim webReq As HttpWebRequest
Dim webRes As HttpWebResponse
Dim webStream As IO.StreamReader
Dim _answer As String
webReq = System.Net.HttpWebRequest.Create(TextBox1.Text)
webReq.Timeout = 10000
webReq.Method = WebRequestMethods.Http.Get
webRes = webReq.GetResponse
webStream = New IO.StreamReader(webRes.GetResponseStream(), System.Text.Encoding.ASCII())
_answer = webStream.ReadToEnd
RichTextBox1.Text = _answer
webRes.Close()
webRes = Nothing
webReq = Nothing
任何想法,提示都值得赞赏!
预先感
谢克里斯
I'm having a hard time figuring out while a HttpWebRequest in .NET 4.0 creates a socket connection for each request but isn't able to close the socket afterwards.
When I execute e.g 50 HttpWebRequests I see 50 TCP socket connections in the WAIT state in netstat.
I already reduced the code to a minimum:
Dim webReq As HttpWebRequest
Dim webRes As HttpWebResponse
Dim webStream As IO.StreamReader
Dim _answer As String
webReq = System.Net.HttpWebRequest.Create(TextBox1.Text)
webReq.Timeout = 10000
webReq.Method = WebRequestMethods.Http.Get
webRes = webReq.GetResponse
webStream = New IO.StreamReader(webRes.GetResponseStream(), System.Text.Encoding.ASCII())
_answer = webStream.ReadToEnd
RichTextBox1.Text = _answer
webRes.Close()
webRes = Nothing
webReq = Nothing
Any idea, hint is appreciated!
Thanks in advance
Chris
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在我对这个话题有了更多的了解之后,我现在可以给自己一个答案了。
每当您打开套接字并关闭它时,它都会在完全关闭之前进入“TIME-WAIT”状态。此状态应防止后续 tcp 连接稍后收到延迟的 tcp 数据包。
我正在处理一个向服务器发送数千个 CGI 请求的应用程序。问题是服务器使用 HTTP/1.0,这意味着每个请求都会打开一个新套接字,并在交换数据后立即关闭它。
一段时间后,netstat 中显示数千个 tcp 连接处于“TIME-WAIT”状态。套接字,或者更准确地说是端口,已经耗尽。 Windows 没有为应用程序提供新的套接字以用于新的 CGI 请求。一段时间后,所有 TIME-WAIT 套接字都关闭,应用程序可以继续通信。这个问题源于服务器的 HTTP/1.0 性质。
从 Windows 的角度来看,此问题有两个“修复”。通过调整注册表,您可以允许 Windows 管理比默认 5000 个 tcp 连接更多的连接(我读到一个好的上限可以是 20.000)。另一种选择是减少 TIME-WAIT 时间本身。这也可以通过调整注册表来完成。这两种选择都不能真正解决我们巨大的套接字耗尽问题。
在最终的解决方案中,我们使用了名为“SO-LINGER”的 TCP 套接字选项。创建端口时设置此选项可以跳过 TCP 套接字的 TIME-WAIT 状态。
请记住,这种状态的存在是有原因的!跳过它是最后的选项之一,并且满足我们的需求,因为我们正在通过套接字传输几个字节。在使用此选项之前,请考虑可能的影响。
该项目是用 VB .NET 4.0 开发的。我用来创建套接字的代码发布如下:
after I've gained some more insight on this topic, I'm able to give an answer to myself now.
Whenever you open a socket and close it, it enters the "TIME-WAIT" status before being closed completely. This state should prevent that a following tcp connection receives delayed tcp-packets late on.
I was dealing with an application that posts several thousand CGI requests to a server. Problem was the server using HTTP/1.0 which means that every request opened a new socket and closed it immediately after exchanging the data.
After a while thousands of tcp connections where shown in netstat within the "TIME-WAIT" status. The sockets, or to be more precise ports, became exhausted. Windows was not giving the application new sockets for new CGI requests. After a while all the TIME-WAIT sockets were closed and the application could continue to communicate. This problem was originated in the HTTP/1.0 nature of the server.
There are two "fixes" for this problem from a Windows point of view. By tweaking the REGISTRY you can allow Windows to manage more then the default 5000 tcp connections (I've read a good upper limit can be 20.000). The other option is to reduce the TIME-WAIT time itself. This can be also done by tweaking the REGISTRY. Both options were no real solution to our massive socket-exhaustion-problem.
In the final solution we've used a TCP socket option called "SO-LINGER". Setting this option while creating the port allows to skip the TIME-WAIT state of a TCP socket.
Please keep in mind that this state exists for a reason! Skipping it was one of the last options and suits our needs because we are transmitting a couple bytes over the socket. Before using this option, consider possible impacts.
The project was developed in VB .NET 4.0. The code I've used to create the socket is posted below:
您的意思是“TIME_WAIT”吗?如果是这样,请完成您的 50 个请求,去喝杯咖啡,回到您的盒子,使用 netstat 重新检查。
关闭 TCP 套接字会执行终止握手并将套接字对象排队等待释放。 TCP 设计实际上在几分钟内不会释放套接字 - 即使在成功连接终止和连接之后,某些数据包仍可能通过慢速路由继续传输。因此,在任何此类剩余连接消失之前,不得将套接字重新分配给另一个连接。
平均值,
马丁
Do you mean 'TIME_WAIT'? If so, do your 50 requests, go for a coffee, come back to your box, recheck with netstat.
Closing a TCP socket performs the terminate handshake and queues the socket object for release. The socket is not actually released for some minutes by TCP design - some packets may still be on their way by slow routes even after a successful connection termination & so the socket must not be reallocated to another connection until any such leftovers have died.
Rgds,
Martin