Getting "The underlying connection was closed: An unexpected error occurred on a receive." on FTPWebResponse.close() - vb.net

I have a VB.Net function that will check if the FTP directory exists, otherwise create the directory.
The function works fine at first, but when the number of files in the FTP directory has reached a certain limit, response.close() in the finally block throws an exception : System.Net.WebException:The underlying connection was closed: An unexpected error occurred on a receive..
my function
Public Function funFTPCheckFolder(ByVal ftpPath As String, Optional ByVal bCreate As Boolean = False) As Boolean
Dim request As FtpWebRequest = Nothing
Dim response As FtpWebResponse = Nothing
Dim strReader As StreamReader = Nothing
Try
request = WebRequest.Create(ftpPath)
With request
.Credentials = New NetworkCredential(_username, _password)
.Method = WebRequestMethods.Ftp.ListDirectory
.KeepAlive = False
'.UsePassive = True
End With
response = CType(request.GetResponse, FtpWebResponse)
Catch ex As Exception
funFTPCheckFolder = False
If (bCreate = True) Then
request = WebRequest.Create(ftpPath)
With request
.Credentials = New NetworkCredential(_username, _password)
.Method = WebRequestMethods.Ftp.MakeDirectory
' .KeepAlive = False
.UsePassive = True
End With
response = CType(request.GetResponse, FtpWebResponse)
funFTPCheckFolder = True
End If
Exit Function
Finally
If response IsNot Nothing Then
response.Close()
response = Nothing
End If
If request IsNot Nothing Then
request.Abort()
End If
End Try
Return True
End Function
In this case, when the file amount in the FTP directory reached 481, an exception is thrown.
exception message
After moving one file to the subdirectory, it works fine again, so it seems to be a problem with the amount of file in the directory.
For now the only way I can come up with is wrap it with try/catch, but not sure will it cause any other error.
Try
If response IsNot Nothing Then
response.Close()
End If
Catch ex As Exception
End Try
I want to find out what exactly cause the problem, any thoughts would be appreciated!

Related

The underlying connection was closed thrown in 40th iteration of VB.Net application

This question appears multiple times on StackExchange but I just can't solve it. Most answers say that this arises due to SSL or TLS issues and to set the protocol to TLS10 or to use KeepAlive.
In my case, I am calling my own PHP endpoint and not using SSL. The server is hosted on GoDaddy.
I am retrieving records from the server. Due to the large size of the returned data, I placed the calls in a loop. The loop runs and fetches data for 40-50 iterations before throwing this error. It is not a timeout issue as the error is thrown within milliseconds.
I suspect a stream or connection is not closing and the VB.Net program is running out of resources or the server has too many open connections.
The code below is slightly abridged to remove sensitive info:
While True
' Create the request
uri = New Uri(My.Settings.ServerURL & My.Settings.GetEmployeeRecords)
request = DirectCast(WebRequest.Create(uri), HttpWebRequest)
' Add user credentials
creds = New CredentialCache
creds.Add(uri, "Basic", New NetworkCredential(My.Settings.UserId, My.Settings.Password))
With request
.Method = "POST"
.ContentType = "application/x-www-form-urlencoded"
.AutomaticDecompression = DecompressionMethods.GZip + DecompressionMethods.Deflate
.Credentials = creds
.KeepAlive = False
.ProtocolVersion = HttpVersion.Version10
.ConnectionGroupName = Guid.NewGuid().ToString()
.UserAgent = "VB.NET App"
.AllowAutoRedirect = False
End With
' Add parameters
strPostData = String.Format("offset={0}&limit={1}", iOffset, iLimit)
request.ContentLength = strPostData.Length
Try
Using sw As New StreamWriter(request.GetRequestStream)
sw.Write(strPostData)
sw.Close()
End Using
Catch ex As Exception
e.Result = "Error Setting Request Data"
Exit Sub
End Try
' Send the request to the server
Try
response = DirectCast(request.GetResponse, HttpWebResponse)
Catch ex As WebException
e.Result = "Error Sending Request" **<-- This is where it is thrown**
Exit Sub
End Try
' Open the response
Try
reader = New StreamReader(response.GetResponseStream)
Catch ex As Exception
e.Result = "Error Reading Request"
Exit Sub
End Try
' Read the full response
rawresp = reader.ReadToEnd()
reader.Close()
response.Close()
' We should never get a blank response
If rawresp = "" Or rawresp = "[]" Then
e.Result = "Blank Response"
Exit Sub
End If
' The response should be in JSON. Parse it
Try
jResults = Linq.JObject.Parse(rawresp)
Catch ex As Exception
e.Result = "Error parsing response"
Exit Sub
End Try
' Get the complete response into jResults
' The jResults would contain {statuscode, statusDescription, data[]} where the data element would be an array of employees
' Check for error returned in response JSON
If jResults("statusCode").ToString = "404" Then
Exit While
End If
If jResults("statusCode").ToString <> "0" Then
e.Result = "Error received from server"
Exit Sub
End If
' Get the array for the employee records
Try
jEmployees = Linq.JArray.Parse(jResults("data").ToString)
Catch ex As Exception
e.Result = "Response Does Not Contain Employee Array"
Exit Sub
End Try
' Everything is fine. Add the recordds to the local database
SaveEmployeesToLocalDB(jEmployees)
iCount = jEmployees.Count
iOffset += iCount
iTotalRecords += iCount
If iCount = 0 Then
Exit While
End If
If iTotalRecords Mod (20 * iLimit) = 0 Then
Application.DoEvents()
Threading.Thread.Sleep(3000)
End If
End While

Check if URL has valid page

I want to check if URL has valid page (not 404, just 200).
Code I've tried:
Dim request As HttpWebRequest = DirectCast(WebRequest.Create(myurl), HttpWebRequest)
request.KeepAlive = True
Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
If response.StatusCode = HttpStatusCode.OK Then
MsgBox("OK")
End If
Yet every URL that I enter leaves OK response, even if I enter http://mywebsite.com/blahblah.
It's not same on all websites (works fine with example.com), but it doesn't work on my website. Why?
In my browser I see 404 page, but code says it's OK.
Edit: Just to mention that my website has Cloudflare on.
Try this out and see if it work's for you... As mentioned above in my comment's:
A 404 just means the page isn't found on the server, status will return ok even if a page isn't found and the server was reached and responded
Public Class WebPage
Public Property PageSource As String = String.Empty
Public Property Status As HttpStatusCode = HttpStatusCode.NotFound
Public Property WebError As String = String.Empty
End Class
Public Shared Function GetWebPage(ByVal Website As String) As WebPage
Dim web As New WebPage() With {.Status = HttpStatusCode.OK}
Try
Using source As New System.Net.WebClient()
web.PageSource = source.DownloadString(Website)
End Using
Return web
Catch exweb As WebException
If exweb.Status = WebExceptionStatus.ProtocolError AndAlso exweb.Message.Contains("404") Then
web.Status = HttpStatusCode.NotFound
Else
web.Status = HttpStatusCode.BadRequest
End If
web.WebError = exweb.Message
Catch ex As Exception
web.Status = HttpStatusCode.NotFound
web.WebError = ex.Message
End Try
Return web
End Function
Usage Example
Dim webObj As WebPage = GetWebPage("THESITE")
If Not String.IsNullOrEmpty(webObj.WebError) Then
MessageBox.Show(webObj.WebError)
ElseIf webObj.Status = HttpStatusCode.OK Then
MessageBox.Show("OK")
End If
This will do what you want.
Function URLExists(url As String) As Boolean
Dim Request As Object
Dim ff As Integer
Dim rc As Variant
On Error GoTo EndNow
Set Request = CreateObject("WinHttp.WinHttpRequest.5.1")
With Request
.Open "GET", url, False
.send
rc = .StatusText
End With
Set Request = Nothing
If rc = "OK" Then URLExists = True
Exit Function
EndNow:
End Function

VB.net - see if remote file exists

I have a function to check if a remote file exists after being passed the URL. Assuming it doesn't exist the function would return 0 to be used in another sub. Here's what I have:
Public Function RemoteFileExists(ByVal fileurl As String) As Integer
Dim request As FtpWebRequest = DirectCast(WebRequest.Create(fileurl), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.GetFileSize
Dim response As FtpWebResponse = DirectCast(request.GetResponse(), FtpWebResponse)
If response.StatusCode = FtpStatusCode.ActionNotTakenFileUnavailable Then
RemoteFileExists = 0
Exit Function
End If
Dim fileSize As Long = response.ContentLength
MsgBox(fileSize)
If fileSize > 0 Then
RemoteFileExists = 1
Else
RemoteFileExists = 0
End If
End Function
When I run the app and purposely supply a URL that doesn't exist Visual Studio gives me System.Net.WebException was unhandled. Message=The remote server returned an error: (550) File unavailable (e.g., file not found, no access).
I assumed that the "if response.StatusCode..." would handle that rather than shutting down the program.
Any help appreciated.
DWM
First of all you should switch from Integer to Boolean since you only return either 1 or 0 anyway. A Boolean can be either True or False.
Secondly, you should wrap everything in a Try/Catch block to handle any error that might occur. Wrapping code in Try/Catch can catch most errors (except for the most extreme ones) and putting it around code that could throw an error saves you from having your application crash for the more simple errors.
And finally, you should use Return <value> instead of RemoteFileExists = <value>, since Return will both return the wanted value AND exit the function.
Example implementation:
Public Function RemoteFileExists(ByVal fileurl As String) As Boolean
Try
Dim request As FtpWebRequest = DirectCast(WebRequest.Create(fileurl), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.GetFileSize
Dim response As FtpWebResponse = DirectCast(request.GetResponse(), FtpWebResponse)
If response.StatusCode = FtpStatusCode.ActionNotTakenFileUnavailable Then
Return False 'Return instead of Exit Function
End If
Dim fileSize As Long = response.ContentLength
MsgBox(fileSize)
If fileSize > 0 Then
Return True
Else
Return False
End If
Catch ex As Exception 'Catch all errors
'Log the error if you'd like, you can find the error message and location in "ex.Message" and "ex.StackTrace".
MessageBox.Show("An error occurred:" & Environment.NewLine & ex.Message & Environment.NewLine & ex.StackTrace, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return False 'Return False since the checking failed.
End Try
End Function
In the Catch block, ex.Message is the error message, and ex.StackTrace is where in the code the error occurred.

Web request not repeating after failure, try/catch not working

I am trying to send a web request to a Snom PA1 bell. The bell rings periodically throughout the day, but occasionally times out trying to contact the bell. That would be fine, but after this happens a couple times, the web request stops sending altogether. the sub still runs, but no bells. Also, while debugging, the webrequest throws a webexception that is not handled by the catch, even though it is contained within the try/catch.
Does anyone know why the web request would stop working after a failure?
Private Sub ringIPBell(ByVal params() As Object, Optional ByVal secondattempt As Boolean = False)
Dim IPaddress As String = params(0)
Dim ringSeconds As Double = params(1)
Dim wr As Net.HttpWebRequest
If ringSeconds = 2 Then
wr = Net.HttpWebRequest.Create("http://" & IPaddress & "/line_login.htm?l=2")
Else
wr = Net.HttpWebRequest.Create("http://" & IPaddress & "/line_login.htm?l=1")
End If
wr.Method = "post"
wr.CachePolicy = New System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore) 'added Oct2010
wr.Credentials = New Net.NetworkCredential("correctName", "correctPassword")
Dim postdata As String = "PLAY_RINGER:1=Play Ringer"
wr.ContentLength = postdata.Length + 2
Dim requestStream As IO.Stream, strmwrit As IO.StreamWriter
Try
requestStream = wr.GetRequestStream()
strmwrit = New IO.StreamWriter(requestStream)
strmwrit.WriteLine(postdata)
strmwrit.Close()
Dim responsestream As New IO.StreamReader(wr.GetResponse.GetResponseStream)
Catch ex As System.Net.WebException
If Not secondattempt Then
ringIPBell(params, True)
End If
Dim testvar As String = ex.ToString
Catch ex As Exception
Beep()
End Try
Also, I previously had the following code ringing the bell, but it would only work for one of the two bells, Even though as far as i can tell their settings were identical.
requestStream = wr.GetRequestStream()
strmwrit = New IO.StreamWriter(requestStream)
strmwrit.WriteLine(postdata)
strmwrit.Close()
requestStream.Close()
As suggested I broke out the responestream line as such:
requestStream = wr.GetRequestStream()
strmwrit = New IO.StreamWriter(requestStream)
strmwrit.WriteLine(postdata)
strmwrit.Close()
it breaks on "requestStream = wr.GetRequestStream()"
with the error:
"A first chance exception of type 'System.Net.WebException' occurred in System.dll
Additional information: The operation has timed out"

VB.NET - Checking FTP directory exists always returns true

Can anybody tell me why the function below always returns true, even if the FTP directory in question does not exist?
The value of directoryURL which I pass in is of the form:
ftp://ip_address/directory/subdirectory/
and has a trailing forward slash.
Public Function DoesDirectoryExist(directoryUrl As String) As Boolean
' Check that the target URL is properly formatted
If Not directoryUrl.StartsWith("ftp://") Then directoryUrl = "ftp://" & directoryUrl
' Create a web request
Dim request As FtpWebRequest = DirectCast(WebRequest.Create(directoryUrl), FtpWebRequest)
request.Credentials = New NetworkCredential(_userName, _password)
request.Method = WebRequestMethods.Ftp.ListDirectory
' Try and list the contents of the directory
Try
Using response As FtpWebResponse = DirectCast(request.GetResponse(), FtpWebResponse)
' We have been succesful so the directory exists
Return True
End Using
Catch ex As WebException
Dim response As FtpWebResponse = DirectCast(ex.Response, FtpWebResponse)
If response.StatusCode = FtpStatusCode.ActionNotTakenFileUnavailable Then
Return False
Else
Throw New ApplicationException("Unable to determine if FTP directory exists.")
End If
End Try
End Function
Weird. This works for me (I don't cast the request but I guess that shouldn't matter). This is the code I usually rely on:
Dim response As FtpWebResponse = request.GetResponse()
Using (response)
found = True
End Using
The alternative you have is reading the list of directories:
Using sr As New System.IO.StreamReader(response.GetResponseStream())
Using sw As New System.IO.StreamWriter("tempfile", False)
sw.Write(sr.ReadToEnd())
End Using
End Using
In the worst scenario, it should help you to tackle the problem (e.g., it always founds a directory called "ghost", which you might use to trigger the not-found).
Method 1
Public Function DirectoryExists(directory As String) As Boolean
Dim directoryExists__1 As Boolean
Dim request = DirectCast(WebRequest.Create(directory), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.ListDirectory
request.Credentials = New NetworkCredential("user", "pass")
Try
Using request.GetResponse()
directoryExists__1 = True
End Using
Catch generatedExceptionName As WebException
directoryExists__1 = False
End Try
Return directoryExists__1
End Function
Method 2
If Not DirectoryExists("ftp://" + FTPSettings.IP + "/" + lo_ScreenShotPath) Then
reqFTP = DirectCast(FtpWebRequest.Create(New Uri("ftp://" + FTPSettings.IP + "/" + lo_ScreenShotPath)), FtpWebRequest)
End If
i hope may i help this...