I try to read file list from FTP from direcotry that contains over 1000 files.
I do it like this :
public static FtpWebRequest GetRequest(string uri)
{
FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
req.Credentials = new NetworkCredential("login", "password");
req.KeepAlive = false;
req.UseBinary = false;
req.UsePassive = true;
return req;
}
public static bool CheckConnection()
{
FtpWebResponse respSize = null;
try
{
FtpWebRequest reqFTP = GetRequest(#"ftp://myftp.com");
reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
respSize = (FtpWebResponse)reqFTP.GetResponse();
respSize.Close();
respSize = null;
reqFTP.GetResponse().Close();
return true;
}
catch (Exception ex)
{
//...
}
finally
{
if (respSize != null)
respSize.Close();
}
return false;
}
I get an error:
The remote server returned an error:
(451) Local error in processing.
at
System.Net.FtpWebRequest.SyncRequestCallback(Object
obj)
at
System.Net.FtpWebRequest.RequestCallback(Object
obj)
at
System.Net.CommandStream.Dispose(Boolean
disposing)
at System.IO.Stream.Close()
at System.IO.Stream.Dispose()
at
System.Net.ConnectionPool.Destroy(PooledStream
pooledStream)
at
System.Net.ConnectionPool.PutConnection(PooledStream
pooledStream, Object owningObject,
Int32 creationTimeout, Boolean
canReuse)
at
System.Net.FtpWebRequest.FinishRequestStage(RequestStage
stage)
at
System.Net.FtpWebRequest.SyncRequestCallback(Object
obj)
at
System.Net.FtpWebRequest.RequestCallback(Object
obj)
at
System.Net.CommandStream.Abort(Exception
e)
at
System.Net.CommandStream.CheckContinuePipeline()
at
System.Net.FtpWebRequest.DataStreamClosed(CloseExState
closeState)
at
System.Net.FtpDataStream.System.Net.ICloseEx.CloseEx(CloseExState
closeState)
at
System.Net.FtpDataStream.Dispose(Boolean
disposing)
at System.IO.Stream.Close()
at
System.Net.FtpWebResponse.Close()
at CheckConnection()
does anyone knows what is going on ?
regards
Marcin
From RhinoSoft (makers of the FTP software Serv-U):
"A 451 reply code may be sent in response to any command initiating a file transfer. It is a transient negative response, which means the error condition is a temporary one. It is usually sent in response to the server encountering an unexpected local error when processing data it is transferring or receiving. In this case, the client is encouraged to restart the FTP transaction and try again." [1]
So, it may be an issue with communication between your software and the FTP server, not necessarily an issue with your software itself.
It can't hurt to increase the length of the Timeout property of FtpWebRequest, but that's not likely to be the cause based on my research.
Related
I'm transferring an updated program to the client through FTP server. The folder has a total size of 250 MB, I'm facing this problem.
"System.Net.WebException: System error. ---> System.Net.InternalException: System error.
at System.Net.PooledStream.PrePush(Object expectedOwner) at System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse) at System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage) at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
at System.Net.FtpWebRequest.RequestCallback(Object obj) at System.Net.CommandStream.Dispose(Boolean disposing) at System.IO.Stream.Close()\r\n at System.IO.Stream.Dispose() at System.Net.ConnectionPool.Destroy(PooledStream pooledStream) at System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse) at System.Net.FtpWebRequest.AttemptedRecovery(Exception e) at System.Net.FtpWebRequest.SubmitRequest(Boolean async)
--- End of inner exception stack trace ---
at System.Net.FtpWebRequest.GetResponse()
at WMSUpdateManager.FTPManagerClass.getFileSizeOfDir(String filename) in C:\Users\USER\source\repos\WMSUpdateManager\WMSUpdateManager\FTPManagerClass.cs:line 472
at WMSUpdateManager.FTPManagerClass.getFileSize(String filename) in C:\Users\USER\source\repos\WMSUpdateManager\WMSUpdateManager\FTPManagerClass.cs:line 439 at WMSUpdateManager.FTPManagerClass.DownloadFileSet(String remoteFile, String localFile) in C:\Users\USER\source\repos\WMSUpdateManager\WMSUpdateManager\FTPManagerClass.cs:line 118"
I'm also using this block in a recursive function to get the directory size.
FtpWebRequest sizeRequest;
sizeRequest = (FtpWebRequest)FtpWebRequest.Create(host + "/" + filename);
sizeRequest.Credentials = new NetworkCredential(username, password);
sizeRequest.UsePassive = true;
sizeRequest.KeepAlive = true;
sizeRequest.Method = WebRequestMethods.Ftp.GetFileSize;
sizeRequest.UseBinary = true;
sizeRequest.EnableSsl = false;
sizeRequest.Timeout = -1;
FtpWebResponse respSize = (FtpWebResponse)sizeRequest.GetResponse(); //problem at line 472
size = respSize.ContentLength;
sizeRequest = null;
respSize.Close();
My log file.
This looks like the culprit:
System.Net Information: 0 : [7640] FtpControlStream#54444047 - Received response [421 No-transfer-time exceeded. Closing control connection.]
Your FTP server closes your connection after some time, if you do not do any file transfer. "Size" requests likely do not count as "transfers".
What you can do is to force FtpWebRequest to open new connection, before the server closes the current one.
For example, this will make .NET open new connection every minute:
sizeRequest.ConnectionGroupName = DateTime.Now.ToString("yyyy-MM-dd-HH-mm");
See also:
Best method to close a keep-alive FTP or FTPS connection in C# (.NET 4.6)?
C# - FtpWebRequest - Multiple requests over the same connection/login
in my program in c#, i need to connect to a website by a specified ip.for this I use ServicePoint.BindIPEndPointDelegate,but it doesn't work. I searched and found this:
when server supports ipv6, we try to establish connection with server using its ipv6 address. But an ipv4 address is specified in the callback. Since the socket has already been created with AddressFamily.InterNetworkv6 when the delegate is called, the bind to an IPv4 address fails. So the delegate is called again. But the same endpoint is returned so the bind fails again. This repeats Integer.MaxValue times and then OverflowException is thrown. Note Integer.MaxValue is a really big value and it looks as though the code has gone to an infinite loop.
now how can I solve this problem? I need to connect with specified ip.
the code :
private void button1_Click(object sender, EventArgs e)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://www.scopus.com");
request.ServicePoint.BindIPEndPointDelegate = new BindIPEndPoint(BindIPEndPointCallback);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream data = response.GetResponseStream();
StreamReader reader = new StreamReader(data);
var result = reader.ReadToEnd();
reader.Close();
response.Close();
txtResult.Text = result;
}
public static IPEndPoint BindIPEndPointCallback(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount)
{
IPAddress address=IPAddress.Parse("77.81.99.66");
if (retryCount == 5)
return null;
return new IPEndPoint(address, 7070);
}
It was all working an hour ago and many days ago.
The link i try to ping is:
Link to ping
This is the code in form1:
nc = new NetworkConnection();
bool bval = nc.PingConnection(satellite_address);
if (bval)
{
label19.Visible = true;
label19.Text = "Internet Access";
}
else
{
label19.Visible = true;
label19.Text = "No Internet Access";
}
When it's trying to execute this line:
bool bval = nc.PingConnection(satellite_address);
It's going to the nc class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.NetworkInformation;
using System.IO;
using System.Windows.Forms;
namespace mws
{
class NetworkConnection
{
public NetworkConnection()
{
}
public bool PingConnection(string url)
{
bool Result = false;
using (Ping pp = new Ping())
{
byte[] buffer = Encoding.ASCII.GetBytes("samplestring");
int timeout = 120;
try
{
PingReply reply = pp.Send(url, timeout, buffer);
if (reply.Status == IPStatus.Success)
Result = true;
}
catch (Exception)
{
Result = false;
}
}
return Result;
}
}
}
In the nc class when trying to do the line:
PingReply reply = pp.Send(url, timeout, buffer);
It's jumping to the catch block and throws a PingException:
An exception occurred during a Ping request
And then in Form1 the result it return is that there is no internet access but there is internet and I can surf to the url no problems.
This is the complete exception message:
System.Net.NetworkInformation.PingException was caught
HResult=-2146233079
Message=An exception occurred during a Ping request.
Source=System
StackTrace:
at System.Net.NetworkInformation.Ping.Send(String hostNameOrAddress, Int32 timeout, Byte[] buffer, PingOptions options)
at System.Net.NetworkInformation.Ping.Send(String hostNameOrAddress, Int32 timeout, Byte[] buffer)
at mws.NetworkConnection.PingConnection(String url) in d:\C-Sharp\Download File\Downloading-File-Project-Version-012\Downloading File\NetworkConnection.cs:line 33
InnerException: System.Net.Sockets.SocketException
HResult=-2147467259
Message=No such host is known
Source=System
ErrorCode=11001
NativeErrorCode=11001
StackTrace:
at System.Net.Dns.GetAddrInfo(String name)
at System.Net.Dns.InternalGetHostByName(String hostName, Boolean includeIPv6)
at System.Net.Dns.GetHostAddresses(String hostNameOrAddress)
at System.Net.NetworkInformation.Ping.Send(String hostNameOrAddress, Int32 timeout, Byte[] buffer, PingOptions options)
InnerException:
Line 33 is:
PingReply reply = pp.Send(url, timeout, buffer);
What could be the reason that this exception show up ? it didn't show up before ever my program is working for some yeras now.
And what or how should i handle it ?
You cannot pass a full URL to the Send method of the Ping class. The parameter string hostNameOrAddress needs to be
A String that identifies the computer that is the destination for the ICMP echo message. The value specified for this parameter can be a host name or a string representation of an IP address.
So you can only pass in www.sat24.com or the IP of the host 82.94.176.100 (taken from the CommandLine ping www.sat24.com).
If you want to pass a full URL to your method you need to extract the Host from that URL to perform your Ping. For this case you can take the Uri class
Uri uri = new Uri(url);
PingReply reply = pp.Send(uri.Host, timeout, buffer);
PingReply reply = pp.Send(url, timeout, buffer);
"No such host is known"
My bet is that no such host is known.
You should ping "www.sat24.com" not "http://www.sat24.com/..."
Ping.Send doesn't say it accepts a URL
public PingReply Send(
string hostNameOrAddress,
int timeout,
byte[] buffer
)
hostNameOrAddress A String that identifies the computer that is the destination for the ICMP echo message. The value specified for this parameter can be a host name or a string representation of an IP address.
http://msdn.microsoft.com/en-us/library/ms144954(v=vs.110).aspx
I have an API that takes in XML and ultimately uploads files based on information in the XML. The uploads are on a schedule (also from XML), and I have tested everything surrounding it and know it works.
I am getting an error about 40% of the time on the first file that I attempt to upload in each time cycle (time cycle = 45 minutes for some files, 30 minutes for others).
Here is my code for the upload:
try {
LoggerFTP.Log("Uploading file: " + filename, false);
// Create the request.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(appSettingsFTP.ftpUrl + #"/" + filename);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Timeout = 6000000; //set to 100 minutes
//request.Timeout = -1; //set to infinite
// Add the login credentials.
request.Credentials = new NetworkCredential(appSettingsFTP.ftpLogin, appSettingsFTP.ftpPassword);
// Grab the file contents.
StreamReader sourceStream = new StreamReader(appSettingsFTP.uploadFileDirectory + filename);
byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
request.ContentLength = fileContents.Length;
// Copy the file contents to the outgoing stream.
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
//Logger.Log(filename.ToString() + " " + "Upload Complete, Status: " + response.StatusCode + " " + response.StatusDescription, false);
//Took response.StatusDescription out because it appears to be creating extra line feeds.
LoggerFTP.Log(filename.ToString() + " " + "Upload Complete, Status: " + response.StatusCode, false);
}
catch (Exception ex) {
LoggerFTP.Log(ex.ToString(), false);
}
I have researched the issue and saw something online about it potentially being a speed thing. Like, there is a timeout. But I have my timeout set to 100 minutes for my FtpWebRequest, so it can't possibly be that? I don't know. This is also running as a service so it is hard to test this aspect of the code.
Here is the exception that is getting logged in my logger (e.ToString):
System.Net.WebException: System error. ---> System.Net.InternalException: System error.
at System.Net.PooledStream.PrePush(Object expectedOwner)
at System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse)
at System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage)
at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
at System.Net.FtpWebRequest.RequestCallback(Object obj)
at System.Net.CommandStream.Dispose(Boolean disposing)
at System.IO.Stream.Close()
at System.IO.Stream.Dispose()
at System.Net.ConnectionPool.Destroy(PooledStream pooledStream)
at System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse)
at System.Net.FtpWebRequest.AttemptedRecovery(Exception e)
at System.Net.FtpWebRequest.SubmitRequest(Boolean async)
--- End of inner exception stack trace ---
at System.Net.FtpWebRequest.GetRequestStream()
at CPMainSpringAPIExportsSC.UploadFTP.FTPUploadMethod(String viewname, String filename)
I am getting exactly the same stack trace in an SSIS package attempting to FTP over SSL. It works great without SSL, but as soon as I enable SSL, it blows up.
System.Net.WebException: System error. --->
System.Net.InternalException: System error. at
System.Net.PooledStream.PrePush(Object expectedOwner) at
System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse) at
System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage) at
System.Net.FtpWebRequest.SyncRequestCallback(Object obj) at
System.IO.Stream.Close() at
System.Net.ConnectionPool.Destroy(PooledStream pooledStream) at
System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse) at
System.Net.FtpWebRequest.AttemptedRecovery(Exception e) at
System.Net.FtpWebRequest.SubmitRequest(Boolean async)
--- End of inner exception stack trace --- at
System.Net.FtpWebRequest.CheckError() at
System.Net.FtpWebRequest.GetRequestStream() at
ST_0ff7348de65a468bb358ab0206e3721f.ScriptMain.Main() in c:\Users\Stephens\AppData\Local\Temp\Vsta\e664c8a71bb647ff9e9dc6ac32d7b615\ScriptMain.cs:line 155 at
System.Net.FtpWebRequest.CheckError() at
System.Net.FtpWebRequest.GetRequestStream() at
ST_0ff7348de65a468bb358ab0206e3721f.ScriptMain.Main() in c:\Users\Stephens\AppData\Local\Temp\Vsta\e664c8a71bb647ff9e9dc6ac32d7b615\ScriptMain.cs:line 155
Because the error is so generic, I decided to look at the .NET source to see if I can catch a clue about what is breaking. If you go here:
http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Net#{%22pageClientState%22%3A%22type-2844%2Ccsharp%22}
and skip down to line 281, you will see the definition for internal void PrePush(object expectedOwner) which is what is executing when the exception happens. Here is what it looks like:
internal void PrePush(object expectedOwner)
{
lock (this) {
//3 // The following tests are retail assertions of things we can't allow to happen.
if (null == expectedOwner) {
if (null != m_Owner && null != m_Owner.Target)
throw new InternalException();
// new unpooled object has an owner
}
else {
if (null == m_Owner || m_Owner.Target != expectedOwner)
throw new InternalException();
// unpooled object has incorrect owner
}
m_PooledCount++;
if (1 != m_PooledCount)
throw new InternalException();
// pushing object onto stack a second time
if (null != m_Owner)
m_Owner.Target = null;
}
}
Eventually I discovered that FtpWebRequest only supports explicit FTP (port 21) and not implicit FTP (port 990). This was definitively stated here:
Does .NET FtpWebRequest Support both Implicit (FTPS) and explicit (FTPES)?
Anyway, in my case, it was a firewall issue. Originally we configured for implicit FTP, which was ports 989, 990, 49152-65535 (per the vendor's tech staff). I checked with my network guy and we opened up ports 20, 21, 989, 990 and 40000-655535 for explicit and things worked like a champ afterwards.
However, in your case, you appear to have some connection pool excitement going on. There is a good post on this subject here:
How to improve the Performance of FtpWebRequest?
You might want to take a look at mucking around with your connection pool set up and see if you can make some progress. Hope this helps!
Regards,
Stuart
I know this is an old topic, but for anyone with the same problem, the code that is missing is:
request.EnableSsl = false;
I wrote a Windows service using an HttpListener to process the requests from points asynchronously.
It works fine, but sometimes it runs into a problem that requires restarting the service or server to fix. Initially I declared the listener object with:
public HttpListener PointsListener = new HttpListener();
Here is the code of the method, where I starting listening. I'm calling it from the OnStart method of the service:
public string ListenerStart()
{
try
{
if (!PointsListener.IsListening)
{
PointsListener.Prefixes.Add(String.Concat("http://*:", points_port, "/"));
PointsListener.Start();
PointsListener.BeginGetContext(PointProcessRequest, PointsListener);
LogWriter("Http listener activated on port " + points_port);
return "Listener started";
}
else
{
return "Listener is already started!";
}
}
catch (Exception err)
{
LogWriter("Error in LIstenerStart \r\n" + err.ToString());
return ("Error: " + err.Message);
}
}
Here are the methods which process requests:
private void PointProcessRequest(IAsyncResult result)
{
HttpListener listener = (HttpListener)result.AsyncState;
HttpListenerContext context = listener.EndGetContext(result);
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
response.KeepAlive = false;
System.IO.Stream output = response.OutputStream;
try
{
//declaring a variable for responce
string responseString = "<html>My Response: request is not allowed by server protocol</html>";
// Commands and actions to set responceString
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
output.Write(buffer, 0, buffer.Length);
}
catch (Exception err)
{
LogWriter("Error in PointProcessRequest: \r\n" + err.ToString());
}
finally
{
try
{
output.Flush();
output.Close();
response.Close();
}
catch (Exception err)
{
LogWriter("Error in PointProcessRequest CLOSING OUTPUT STREAM: \r\n" + err.ToString());
}
finally
{
PointsListener.BeginGetContext(PointProcessRequest, PointsListener);
}
}
}
It is working well some of the time, but the following error appears in the log:
Error in PointProcessRequest:
System.Net.HttpListenerException: The specified network name is no longer available
в System.Net.HttpResponseStream.Write(Byte[] buffer, Int32 offset, Int32 size)
в ARK_Dealer.ark.PointProcessRequest(IAsyncResult result)
[26.01.2011 9:00:54] Error in PointProcessRequest CLOSING OUTPUT STREAM:
System.InvalidOperationException: Cannot close stream until all bytes are written.
в System.Net.HttpResponseStream.Dispose(Boolean disposing)
в System.IO.Stream.Close()
в ARK_Dealer.ark.PointProcessRequest(IAsyncResult result)
I think that problem appears when some point sends the request to server but before the receiving answer looses the connection.
How can I prevent the exception from being thrown? Will be the response object be properly disposed of automatically? How can I solve the problem?
I'm using a HttpListener in production and I've found the nicest way to resolve this issue, without adding a whole bunch of try/catch blocks which do nothing to communicate the logic of the code at hand; is to quite simply to set Listener.IgnoreWriteExceptions = true; and, voilà no more write exceptions!
There is a related question about this.
What you are doing is fine, since there is nothing else that can be done about the other side closing the connection or the connection being dropped. You might want to catch the exact exception and call output.Dispose() and other cleanup or simply let the finalizers handle the release if it doesn't happen very often.
I had the same problem recently, and solved it by wrapping the output in a try/catch:
try
{
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
output.Write(buffer, 0, buffer.Length);
}
catch (HttpListenerException)
{
// Handle error caused by connection being lost
}
Problem solved!!! I just removed this:
finally
{
PointsListener.BeginGetContext(PointProcessRequest, PointsListener);
}
and inserted this command at the begin of PointProcessRequest method!
IAsyncResult _result = listener.BeginGetContext(new AsyncCallback(PointProcessRequest), listener);
Problem solved at 100%!!!