VB.Net BeginGetResponse“;请求被中止:连接意外关闭;
测试发送web请求的不同方法的吞吐量,因此我创建了一个类WebRequester,它使用BeginGetResponse异步发送请求,并实现BeginGetResponse和BeginRead的回调。从调用代码在循环中发送多个请求时,如果重用同一个HttpWebRequest对象,则会收到以下异常: “请求被中止:连接意外关闭。” 如果我在循环调用代码的每次迭代中创建一个新的HttpWebRequest对象,则不会发生异常 问题是,在每次迭代中创建一个新的HttpWebRequest会导致相当严重的性能下降。这是怎么回事 编辑:忘了提一些事情。使用Visual Studio 2017、.NET 4.5.2、在端口8888上运行的Fiddler和在端口1337上启动的NodeJS Express测试服务器VB.Net BeginGetResponse“;请求被中止:连接意外关闭;,vb.net,asynchronous,Vb.net,Asynchronous,测试发送web请求的不同方法的吞吐量,因此我创建了一个类WebRequester,它使用BeginGetResponse异步发送请求,并实现BeginGetResponse和BeginRead的回调。从调用代码在循环中发送多个请求时,如果重用同一个HttpWebRequest对象,则会收到以下异常: “请求被中止:连接意外关闭。” 如果我在循环调用代码的每次迭代中创建一个新的HttpWebRequest对象,则不会发生异常 问题是,在每次迭代中创建一个新的HttpWebRequest会导致相当严
Imports System.Net
Imports System.Threading
Public Class Form1
Private Sub Test() Handles Button1.Click
'Test using HttpWebRequest.BeginGetResponse
ServicePointManager.DefaultConnectionLimit = 2
Dim iterations as integer = 1000
Dim completedCount As Integer = 0
Dim lock As New Object
Dim mre As New ManualResetEvent(False)
Dim wr As New WebRequester
AddHandler wr.ResponseReceived, Sub(reqState As RequestState)
SyncLock lock
completedCount += 1
If completedCount = iterations Then
mre.Set()
End If
End SyncLock
End Sub
'If I reuse the HttpWebRequest object below in my loop, I receive "The request was aborted: The connection was closed unexpectedly." :(
'Dim req As HttpWebRequest = HttpWebRequest.Create("http://localhost.:1337/")
'req.Proxy = New WebProxy("127.0.0.1", 8888)
For i = 0 To iterations - 1
Dim req As HttpWebRequest = HttpWebRequest.Create("http://localhost.:1337/")
req.Proxy = New WebProxy("127.0.0.1", 8888)
wr.SendRequest(req, 30000)
Next
mre.WaitOne()
End Sub
End Class
Imports System.Net
Public Class RequestState
Private bufferSize As Integer = 1024
Public Property Request As HttpWebRequest
Public Property Response As HttpWebResponse
Public Property ResponseBody As String
Public Property ResponseStream As IO.Stream
Public Property ResponseData As Text.StringBuilder
Public Property ReadBuffer As Byte()
Public Sub New()
ReadBuffer = New Byte(bufferSize) {}
ResponseData = New System.Text.StringBuilder()
End Sub
End Class
Imports System.Net
Public Class WebRequester
'Adapted from https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2
Private mre As New Threading.ManualResetEvent(False)
Public Event ResponseReceived(reqState As RequestState)
Public Event ExceptionRaised(ex As Exception)
Public Sub SendRequest(req As HttpWebRequest, timeOut As Integer)
Try
Dim reqState As New RequestState
reqState.Request = req
Dim result As IAsyncResult = reqState.Request.BeginGetResponse(New AsyncCallback(AddressOf RespCallback), reqState)
Threading.ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, New Threading.WaitOrTimerCallback(AddressOf TimeoutCallback), reqState.Request, timeOut, True)
mre.WaitOne()
reqState.Response.Close()
Catch ex As Exception
RaiseEvent ExceptionRaised(ex)
End Try
End Sub
Private Sub RespCallback(asyncResult As IAsyncResult)
Try
Dim reqState As RequestState = asyncResult.AsyncState
reqState.Response = reqState.Request.EndGetResponse(asyncResult)
reqState.ResponseStream = reqState.Response.GetResponseStream
reqState.ResponseStream.BeginRead(reqState.ReadBuffer, 0, 1024, New AsyncCallback(AddressOf ReadCallback), reqState)
Catch ex As Exception
RaiseEvent ExceptionRaised(ex)
End Try
mre.Set()
End Sub
Private Sub ReadCallback(asyncResult As IAsyncResult)
Try
Dim reqState As RequestState = asyncResult.AsyncState
'Read the buffer, if there is more data, recursively call responseStream.BeginRead
Dim read As Integer = reqState.ResponseStream.EndRead(asyncResult)
If read > 0 Then
reqState.ResponseData.Append(Text.Encoding.ASCII.GetString(reqState.ReadBuffer, 0, read))
Dim ar As IAsyncResult = reqState.ResponseStream.BeginRead(reqState.ReadBuffer, 0, 1024, New AsyncCallback(AddressOf ReadCallback), reqState)
Return
Else
'Request complete!
reqState.ResponseBody = reqState.ResponseData.ToString
reqState.ResponseStream.Close()
reqState.ResponseStream.Dispose()
RaiseEvent ResponseReceived(reqState)
End If
Catch ex As Exception
RaiseEvent ExceptionRaised(ex)
End Try
mre.Set()
End Sub
Private Shared Sub TimeoutCallback(state As Object, timedOut As Boolean)
If timedOut Then
Dim request As HttpWebRequest = state
If Not (request Is Nothing) Then
request.Abort()
End If
End If
End Sub 'TimeoutCallback
End Class
在回答可能的dupe问题时,除了我们都在重用HttpWebRequest对象这一事实之外,我们的情况似乎完全不同,足以提出一个新问题。从技术上讲,我甚至不是在问HttpWebRequest是否可以重用,我真的是在问为什么重用HttpWebRequest时,我会收到我发布的异常。可能重复@GSerg该问题中的OP出现超时问题,我的问题是连接意外关闭。除了我们都在重用HttpWebRequest对象这一事实之外,我们的情况似乎不同到足以引起一个新的问题。从技术上讲,我甚至不是在问HttpWebRequest是否可以重用,而是在问为什么当我这样做时,我会收到我发布的异常。谢谢你!顺便说一句,我添加了HttpWebResponse。在每个请求结束时关闭对我代码的调用,正如您在回答中建议的那个SO问题,异常仍然存在。