Super slow HttpWebRequest - vb.net

I'm making a website scraper for a project I'm doing. I've gotten everything to work great, however, loading the actual page takes F-O-R-E-V-E-R. You can see the page it's loading here:
MCServerList.Net
Here is the code I am using:
private CONST REQUESTURL as string = "http://www.MCServerList.net/?page="
private chunkId as int32 = 1
Dim req As HttpWebRequest = WebRequest.Create(REQUESTURL & chunkId)
Dim res As HttpWebResponse = req.GetResponse()
Dim Stream As Stream = res.GetResponseStream()
I then use "Stream" and load it through the HTMLAgilityPack found free online. It loads the page quickly, however, the initial request usually takes ~20-30 seconds.
Any help would be appreciated!

I just ran the following code and ignoring the first initial compile I average about 3.3 seconds for GetResponse() and 0.2 more seconds for Load(). Are you on a fast connection? Are you sure this is where the bottleneck is?
Option Explicit On
Option Strict On
Imports System.Net
Public Class Form1
Private Const REQUESTURL As String = "http://www.MCServerList.net/?page="
Private chunkId As Int32 = 1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim ST As New System.Diagnostics.Stopwatch()
ST.Start()
Dim req = WebRequest.Create(REQUESTURL & chunkId)
Dim res = req.GetResponse()
Trace.WriteLine(String.Format("GetResponse() : {0}", ST.Elapsed))
Using Stream As System.IO.Stream = res.GetResponseStream()
Dim X As New HtmlAgilityPack.HtmlDocument()
X.Load(Stream)
End Using
Trace.WriteLine(String.Format("Load() : {0}", ST.Elapsed))
ST.Stop()
End Sub
End Class

Related

HttpWebRequest GetRequestStream to Amcrest camera not working

I have an Amcrest IP4M-1051 camera. The API for the camera enables two-way audio. Amcrest provides some freeware called, Amcrest Surveillance Pro, which demonstrates the functionality pretty well. I have a custom VB.NET WPF program in which I'm trying to replicate that functionality, using the NAudio library. My program can stream both the video and audio from the camera. I'm having trouble, though, streaming the audio picked up by my computer's microphone back to the camera. The code so far:
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports NAudio.Wave
Class MainWindow
Dim tcpSender As New TcpClient
Dim endPoint As Net.IPEndPoint
Dim ipAddress As Net.IPAddress
Dim port As Integer
Private Sub Window_Loaded()
'ipAddress = System.Net.IPAddress.Parse("192.168.1.80")
'port = 554
'endPoint = New Net.IPEndPoint(ipAddress, port)
'tcpSender.Connect(endPoint)
Dim waveIn As New NAudio.Wave.WaveIn
waveIn.BufferMilliseconds = 50
waveIn.WaveFormat = New WaveFormat(44100, 2)
AddHandler waveIn.DataAvailable, AddressOf NAudio_DataAvailable
waveIn.StartRecording()
End Sub
Private Sub NAudio_DataAvailable(ByVal sender As Object, ByVal e As NAudio.Wave.WaveInEventArgs)
'Dim encoded() As Byte = codec.Encode(e.Buffer, 0, e.BytesRecorded)
'audioSender.Send(encoded)
Dim buffer As Byte() = e.Buffer 'Encoding.UTF8.GetBytes(e.Buffer)
Dim bytesRecorded As Integer = e.BytesRecorded
WriteToNetwork(buffer, bytesRecorded)
End Sub
Private Sub WriteToNetwork(ByVal buffer As Byte(), ByVal bytesRecorded As Integer)
'tcpSender.Client.Send(buffer)
Dim uri As New Uri("http://admin:PASSWORD#192.168.1.80/cgi-bin/audio.cgi?action=postAudio&httptype=singlepart&channel=1")
Dim request As HttpWebRequest
request = WebRequest.CreateHttp(uri)
request.Timeout = 4000
request.Method = "POST"
request.ContentType = "Audio/G.711A"
request.ContentLength = bytesRecorded
'
'Dim postStream = request.GetRequestStream
Using postStream As IO.Stream = request.GetRequestStream
postStream.Write(buffer, 0, bytesRecorded)
'Using response As HttpWebResponse = request.GetResponse
' Dim responseString As String = New IO.StreamReader(response.GetResponseStream()).ReadToEnd
' If Not String.IsNullOrEmpty(responseString) Then
' Console.WriteLine(responseString)
' End If
'End Using
End Using
End Sub
End Class
This code has a few issues. First of all, the camera is configured to receive AAC codec, and I have to use G.711A because I couldn't get AAC to work at all. By using the G.711A, the WriteToNetwork procedure works the first time (and the camera produces a second of static) and, on the second time, hangs at request.GetRequestStream, producing error: System.Net.WebException: 'The underlying connection was closed: The connection was closed unexpectedly.' Has anyone encountered this before?

How to execute a webrequest asynchronous to parse json

I need to get a value from an API and I'm using the follow code synchronous.
Dim request As HttpWebRequest
Dim response As HttpWebResponse = Nothing
Dim reader As StreamReader
Try
request = DirectCast(WebRequest.Create("http://ecc"), HttpWebRequest)
response = DirectCast(request.GetResponse(), HttpWebResponse)
reader = New StreamReader(response.GetResponseStream())
Dim rawresp As String
rawresp = reader.ReadToEnd()
Dim jResults As JObject = JObject.Parse(rawresp)
Label1.Text = jResults("result").ToString()
Catch ex As Exception
MsgBox(ex.ToString)
Finally
If Not response Is Nothing Then response.Close()
End Try
The problem is that's synchronous, I want to make it async in order not to freeze the form in the while.
How can I async it?
You can easily use WebClient and the nuget package NewtonSoft doing something like this:
Imports System.IO
Imports System.Net
Imports System.Text
Imports Newtonsoft.Json
Public Class Form1
Private ReadOnly wc As New WebClient()
Private Async Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
'stop timer to avoid simultaneous I/O operations
Timer1.Stop()
Dim downloadTasks As New List(Of Task(Of String))
'download api and add as a task of string
Dim APIValue = wc.DownloadStringTaskAsync("https://api.etc")
downloadTasks.Add(Value)
Await Task.WhenAll(downloadTasks)
Dim d = JsonConvert.DeserializeObject(Of Dictionary(Of String, String))(APIValue.Result)
Dim Price As String = d("result").ToString
Label1.Text = Price
Timer1.Start()
End Sub
End Class
Much simpler with HttpClient and JsonNode:
'// Web API:
'// app.MapGet("/api", () => new { id = 1, result = "100", name = "name1" });
Imports System.Net.Http
Imports System.Text.Json.Nodes
Using http = New HttpClient
Dim url = "https://localhost:5000/api"
Dim json = JsonNode.Parse(Await http.GetStreamAsync(url))
Label1.Text = json("result")
End Using

vb.net winforms download without blocking

I'm downloading files .mp3 and my goal is not to have even a minimum GUI freezing during downloading.
My aim is also to display the bites received in a progress bar and through labels.
This code is working, but sometimes is freezing without any reason, sometimes the progress bar doesn't work until file is completely done.
So far, this is the "best" code I found online for a completely working progress bar during a download, but still gets problems.
How do you think I can increase performances? How can I make a resistant and reliable working progressbar? How can I download also large file without GUI freezing? I tried (curiosity) to download a 600 mb file and it completely freeze, not responding and not giving any issue back.
Thanks
EDIT1: I'm trying with this,eventhough I'm lost on high waves.. Any idea on how can I use this code and insert it into Jimi Answer? Answer
Imports System.IO
Imports System.IO.Path
Imports System.Net
Public Class Form1
Private downloader As MyDownloader = Nothing
Private Sub btnStartDownload_Click(sender As Object, e As EventArgs) Handles btnStartDownload.Click
Dim progress = New Progress(Of String)(
Sub(data)
MsgBox("we are on the UI thread here")
End Sub)
Dim url As Uri = New Uri(TextBox1.Text)
downloader = New MyDownloader()
'How can I remove this second? I don't need download from url every 1 second.
downloader.StartDownload(progress, url, 1)
End Sub
And
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Net
Imports System.Net.Http
Imports System.Text.RegularExpressions
Imports System.Threading
Public Class MyDownloader
Private Shared ReadOnly client As New HttpClient()
client.DownloadProgressChanged += AddressOf Client_DownloadProgressChanged
client.DownloadFileCompleted += AddressOf Client_DownloadFileCompleted
Private interval As Integer = 0
Private Sub Client_DownloadFileCompleted(ByVal sender As Object, ByVal e As AsyncCompletedEventArgs)
System.Windows.Forms.MessageBox.Show("Download OK!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Public Sub StartDownload(progress As IProgress(Of String), url As Uri, intervalSeconds As Integer)
interval = intervalSeconds * 1000
Task.Run(Function() DownloadAsync(progress, url))
End Sub
Private Sub Client_DownloadProgressChanged(ByVal sender As Object, ByVal e As DownloadProgressChangedEventArgs)
ProgressBar1.Minimum = 0
Dim receive As Double = Double.Parse(e.BytesReceived.ToString())
Dim total As Double = Double.Parse(e.TotalBytesToReceive.ToString())
Dim percentage As Double = receive / total * 100
label2.Text = $"{String.Format("{0:0.##}", percentage)}%"
ProgressBar1.Value = Integer.Parse(Math.Truncate(percentage).ToString())
End Sub
Private Async Function DownloadAsync(progress As IProgress(Of String), url As Uri) As Task
Dim pattern As String = "<(?:[^>=]|='[^']*'|=""[^""]*""|=[^'""][^\s>]*)*>"
Dim downloadTimeWatch As Stopwatch = New Stopwatch()
downloadTimeWatch.Start()
Do
Try
Dim response = Await client.GetAsync(url, HttpCompletionOption.ResponseContentRead)
Dim data = Await response.Content.ReadAsStringAsync()
data = WebUtility.HtmlDecode(Regex.Replace(data, pattern, ""))
progress.Report(data)
Dim delay = interval - CInt(downloadTimeWatch.ElapsedMilliseconds)
Await Task.Delay(If(delay <= 0, 10, delay))
downloadTimeWatch.Restart()
Catch ex As Exception
End Try
Loop
End Function
End Class
I'm Seriously lost on it, I tried to delete cancel download as I am not going to stop any download and I tried also to delete Download from url every 1 second as I just need one time download for every link.
Thanks

Visual basic HTTP request

Assume, that I wish to use an API from abc.com website.In the api documentation it says,
HTTP/1.x 200 OK
GET /api/now/news
Host: abc.com
Api-Key:xxxxxxxxxx
to get news.
How to write the codes to get a successful response in VB.net
Thank you.
Take https://www.google.com/ for an example, get the source code of the web page in UTF-8 format.
Imports System.Net
Imports System.Text
Public Class Form1
Public Function Getwebcode(ByVal url As String, ByVal encoder As String) As String
Dim myWebClient As WebClient = New WebClient()
Dim myDataBuffer As Byte() = myWebClient.DownloadData(url)
Dim SourceCode As String = Encoding.GetEncoding(encoder).GetString(myDataBuffer)
Return SourceCode
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim back As String = Getwebcode("https://www.google.com/", "UTF-8")
TextBox1.Text = back
End Sub
End Class

How to read binary data/image from WCF REST

I have the following:
Public Interface INorthwindSvc
<OperationContract()>
<WebGet(UriTemplate:="EmployeePictureBytes?id={EmpId}")>
Function GetEmployeePictureBytesById(ByVal EmpId As String) As Byte()
End Interface
I got the method implemented (using EF 4.0) as follows:
Public Function GetEmployeePictureBytesById(ByVal EmpId As String) As Byte() Implements INorthwindSvc.GetEmployeePictureBytesById
Dim ctxt As New NorthwindEntities
Dim q = From c In ctxt.Employees
Where c.EmployeeID = EmpId
Select c.Photo
Return q.FirstOrDefault
End Function
I am able to receive bytes when I access the operation from browser. If I try to access the same using Win Client as follows (an error occurs as shown inline):
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim o As New WebClient
Dim b() As Byte = o.DownloadData(New Uri("http://localhost:8732/WcfWebHttpSvcLib/rest/EmployeePictureBytes?id=2"))
Dim ms As New MemoryStream()
ms.Write(b, 0, b.Length)
Dim original As New System.Drawing.Bitmap(ms) 'error: parameter is not valid
End Sub
I also tried the same using Image.FromStream. But, still no luck.
Can anyone help me on this?
thanks
You're not rewinding the memorystream after writing to it, so trying to read from it will fail That said, even that's unnecessary, as you could just write:
im ms As New MemoryStream(b)
' now call FromStream