WebClient连续下载产生不切实际的下载速度

时间:2017-06-08 15:37:23

标签: vb.net asynchronous download webclient

我正在尝试从路由器硬盘驱动器(具有特定IP地址)连续下载,一个接一个地下载,直到禁用拨动开关。第一次下载通常会产生一个真实的平均下载速度(约60到80 Mbps)。但是,在第一次下载后,相邻下载可能会产生2Gbps,5Gbps甚至无限的平均下载速度。我试过不同的文件大小,但结果几乎相同。这是我用于连续下载测试的代码。

Function SpeedTest()
    Do
        wc.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0)")
        wc.UseDefaultCredentials = True
        wc.Credentials = New NetworkCredential("admin", "admin")

        wc.DownloadFileAsync(New Uri("file://192.XXX.XX.X/Download_Files/1gb.test"), tmp)

        While wc.IsBusy
            Application.DoEvents()
        End While  

        For i As Integer = 1 To 100
            Thread.Sleep(10)
            Application.DoEvents()
        Next
    Loop Until Toggle1.Checked = False
    Return 0
End Function

Private tmp = IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.Temp, "1gb.test")

我相信第一个下载的文件是从相邻下载的缓存文件中恢复的。不确定,如果这是真的。 (我可以看到1GB文件下载在不到一秒的时间内完成。)但如果是这样,我如何删除缓存文件以产生真实的下载速度?

2 个答案:

答案 0 :(得分:1)

经过多次测试并签出C# WebClient disable cache后,HttpWebRequest(在我的情况下,FileWebRequest)在控制下载和上传文件方面更有帮助。此外,在控制缓冲区大小之后,与通过常规方法完成的下载/上载相比,测试得到了更真实的值。此外,在使用 WebClient 时,下载例程的缓冲区大小为64KB,上载的缓冲区大小为8KB。为了产生更接近Windows下载速度的速率,缓冲区大小必须是文件大小的1/100。重复下载仍然没有产生相同的结果。但是,如果从第二次尝试开始将缓冲区大小更改为文件大小的1/1000,则重复下载速率看起来会相似。这是我用来下载的代码。

oRequest = CType(FileWebRequest.Create("file://192.XXX.XX.X/Download_Files/1gb.test"), FileWebRequest)
oRequest.Credentials = New NetworkCredential("admin", "admin")
oResponse = CType(oRequest.GetResponse, WebResponse)
responseStream = oResponse.GetResponseStream()
buffer = New Byte(FileLen(tmp) / 100) {}
fs = New FileStream(tmp, FileMode.Create, FileAccess.Write)
Do
    read = responseStream.Read(buffer, 0, buffer.Length)
    fs.Write(buffer, 0, read)
    Application.DoEvents()
Loop Until read = 0
responseStream.Close()
fs.Flush()
fs.Close()
responseStream.Close()
oResponse.Close()
buffer = Nothing

答案 1 :(得分:0)

这应该允许您连续下载文件,并允许切换取消下载

Private sw As New Stopwatch()
Private wc As WebClient
Private tmp = IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.Temp, "1gb.test")

Private Sub startDownload()
    If wc IsNot Nothing Then
        wc.Dispose()
    End If
    wc = New WebClient()
    wc.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0)")
    wc.UseDefaultCredentials = True
    wc.Credentials = New NetworkCredential("admin", "admin")
    AddHandler wc.DownloadProgressChanged, AddressOf downloadProgressChanged
    AddHandler wc.DownloadDataCompleted, AddressOf downloadDataCompleted
    sw.Reset()
    sw.Start()
    wc.DownloadFileAsync(New Uri("file://192.XXX.XX.X/Download_Files/1gb.test"), tmp)
End Sub

Private Sub cancelDownload()
    If wc IsNot Nothing AndAlso wc.IsBusy Then
        wc.CancelAsync()
    End If
End Sub

Private Sub Toggle1_CheckedChanged(sender As Object, e As EventArgs) Handles Toggle1.CheckedChanged
    If Toggle1.Checked Then
        startDownload()
    Else
        cancelDownload()
    End If
End Sub

Private Sub downloadProgressChanged(sender As Object, e As DownloadProgressChangedEventArgs)
    Me.Invoke(Sub() Me.Text = e.ProgressPercentage)
End Sub

Private Sub downloadDataCompleted(sender As Object, e As DownloadDataCompletedEventArgs)
    sw.Stop()
    Dim message = If(e.Cancelled, "Operation was cancelled!", "Operation completed!")
    If e.Error IsNot Nothing Then
        message &= Environment.NewLine & "Exception: " & e.Error.Message
    End If
    Dim fi As New FileInfo(tmp)
    Dim sizeInBytes = fi.Length
    Dim durationInSeconds = sw.ElapsedMilliseconds / 1000
    message &= String.Format("Downloaded {0} bytes in {1} seconds ({2} Bps)", sizeInBytes, durationInSeconds, sizeInBytes / durationInSeconds)
    ' do what you want with message, if anything
    If Not e.Cancelled Then
        startDownload()
    End If
End Sub