"Link to server lost" or "Broken pipe" error when downloading

Jul 23, 2013 at 2:23 PM
Hi,

Let me start by saying that I like this ftp client very much, it is well written and documented. But I have some strange errors now and then. I am trying to download all files and folders on a server, ceated a "DownloadRecursive" method which should take care of that, but I am getting these "Link to server lost" errors and sometimes it throws the "Broken pipe" exception. Does anybody have an idea what I am doing wrong in this case?

I have played with the connection settings already (according to some other posts), setting the ThreadSafe option true / false, changed timeouts etc. but these changes seem to not have any impact....
            ftp = new FtpClient();
            ftp.Credentials = new NetworkCredential(domain.FTPUsername, domain.FTPPassword);
            ftp.Host = domain.Name;
            ftp.SocketKeepAlive = true;
            ftp.EnableThreadSafeDataConnections = false;
            ftp.DataConnectionType = FtpDataConnectionType.AutoPassive;
            ftp.SetDataType(FtpDataType.Binary);
            ftp.ReadTimeout = 4000;

            try
            {
                ftp.Connect();
            }
            catch (Exception ex)
            {
                Information(this, new FTPHelperEventArgs(String.Format("Connection error: {0}", ex.Message), true, domain));
                return;
            }

try
                {
                    ftp.SetWorkingDirectory(remoteRootFolder);
                    currentLocalFolder = localRootFolder;
                    DownloadRecursive("/", domain);
                }
                finally
                {
                    ftp.Disconnect();
                    ftp.Dispose();
                }
The method which downloads recursive:
        public void DownloadRecursive(string path,TriaDomain domain)
        {
            List<FtpListItem> files = new List<FtpListItem>();
            List<FtpListItem> directories = new List<FtpListItem>();

            foreach (FtpListItem item in ftp.GetListing())
            {
                switch (item.Type)
                {
                    case FtpFileSystemObjectType.Directory:

                        directories.Add(item);

                    break;
                    case FtpFileSystemObjectType.File:

                        files.Add(item);

                    break;
                }
            }

            foreach (FtpListItem item in files)
            {
                using (Stream downloadStream = ftp.OpenRead(item.FullName, FtpDataType.Binary))
                {

                    using (FileStream writeStream = new FileStream(currentLocalFolder + "\\" + item.Name, FileMode.Create))
                    {

                        try
                        {
                            var bytesInStream = new byte[downloadStream.Length];
                            downloadStream.Read(bytesInStream, 0, (int)bytesInStream.Length);

                            writeStream.Write(bytesInStream, 0, bytesInStream.Length);

                            Information(this, new FTPHelperEventArgs(String.Format("Downloaded {0}", item.Name), false, domain));
                        }
                        finally
                        {
                            downloadStream.Close();
                            writeStream.Close();
                        }
                    }
                }


            }

            foreach (FtpListItem item in directories)
            {
                currentLocalFolder = localRootFolder + item.FullName.Replace(remoteRootFolder, String.Empty).Replace("/", "\\");
                Directory.CreateDirectory(currentLocalFolder);

                ftp.SetWorkingDirectory(item.FullName);
                DownloadRecursive(item.FullName,domain);
            }

        }
As you can see I first collect all the files and directories seperatly, then I will download each file one by one. After the files of the current directory are downloaded, I create the directories locally, and repeat the process all again... These exceptions I get are thrown after the first file-list is downloaded (from the most upper level)... What could be wrong with this approach? Anybody?
Coordinator
Jul 23, 2013 at 2:29 PM
I'm not sure what a broken pipe exception is. System.Net.FtpClient doesn't use pipes at all so I suspect that's an error from the server that is being used in a FtpCommandException or FtpException object. Logging the transactions with FtpTrace would give a better idea of what might be happening.
Coordinator
Jul 23, 2013 at 2:31 PM
I'm also not sure about the Link to server lost exception, that's not an error message hard coded in this project, I suspect it might be something the server is sending in a 4xx or 5xx response.
Jul 23, 2013 at 8:26 PM
Thank yoou for your response. I will investigate this further using FtpTrace and will post my findings here (if any).
Jul 24, 2013 at 1:36 PM
Due to a lack of time I switched over to FTPLib which does this job correctly using the same principle. By the way, I have about 50 different websites hosted on different servers, and all of them gave these "pipe" and "link to server lost" errors. I suspect there`s a underlying problem somewhere in this lib but could be wrong offcourse.
Coordinator
Jul 24, 2013 at 1:39 PM
Maybe an error from the .net framework but googling doesn't suggest that either unless you're using named pipes somewhere because System.Net.FtpClient doesn't. At the same time I can't fix problems on this end without knowing what the problem is and a transaction log helps determine that. Any way, best of luck.
Jul 24, 2013 at 1:44 PM
Yes I searched google a lot but the results / topics didn`t make any sense to me neither... My problem is solved anyway, albeit by using a less nifty written lib with less functionality but it does the job. Thank you for your replies!