0

我必须从 ftp 服务器获取文件,但我遇到了一些特定的问题。代码的大致思路是,我必须登录 3 次,然后从服务器获取文件列表。顺利通过,但是当我访问我需要的两个文件时,我得到一个 SocketException:“已建立的连接被主机中的软件中止”

需要明确的是,第一个文件不会生成此异常,但它也不会下载任何内容。第二个完全失败。

代码如下:

static void Main(string[] args)
    {
        IPHostEntry dns = Dns.GetHostEntry("SERVER");

        IPEndPoint serverIP = new IPEndPoint(dns.AddressList[0], 21);

        Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);


        sock.Connect(serverIP);

        FTPRequest("USER firstusername\n", sock);
        FTPRequest("PASS firstpass\n", sock);
        FTPRequest("USER secondusername\n", sock);
        FTPRequest("PASS secondpass\n", sock);
        FTPRequest("USER thirdusername\n", sock);
        FTPRequest("PASS thirdpass\n", sock);
        FTPRequest("TYPE A\n", sock);
        string s = FTPRequest("PASV\n", sock);
        IPEndPoint listenIP = IPEnd(s);
        Socket sock2 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        sock2.Connect(listenIP);
        FTPRequest("LIST\n", sock);


        ArrayList al = new ArrayList();


        try
        {
            byte[] buffer = new byte[25000];

            int bytes = 0;

            bytes = sock2.Receive(buffer);

            Thread.Sleep(1000);

            string stringList = Encoding.ASCII.GetString(buffer, 0, bytes);



            foreach (string st in stringList.Split(' ', '\n'))
            {
                if (st.Contains(".CSV"))
                    al.Add(st.Trim());
            }
        }
        catch (Exception)
        {
            return;
        }

        sock2.Disconnect(false);

        DateTime dt = new DateTime();

        foreach (string st in al)
        {
            DateTime temp = DateTime.ParseExact(st.Split('_', '.')[4], "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture);
            if (temp > dt)
                dt = temp;
        }

        string file1 = "";
        string file2 = "";

        foreach (string st in al)
        {
            if (st.Contains(dt.ToString("yyyyMMdd")))
            {
                if (st.Contains("CAN"))
                    file1 = st;
                else
                    file2 = st;
            }
        }

        FTPRequest("TYPE I\n", sock);

        foreach (string file in new string[] { file1, file2 })
        {
            if (file != "")
            {
                Socket sock3 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                FTPRequest("TYPE I\n", sock);
                sock3.Connect(IPEnd(FTPRequest("PASV\n", sock)));

                FTPRequest("RETR" + file + '\n', sock);

                try
                {
                    byte[] buffer = new byte[25000];

                    int bytes = 0;

                    bytes = sock3.Receive(buffer);


                    FileStream writeStream = new FileStream(@"MYPATH" + file1, FileMode.Create);

                    while (bytes > 0)
                    {
                        writeStream.Write(buffer, 0, bytes);
                        bytes = sock3.Receive(buffer, 0);
                    }


                }
                catch (Exception)
                {
                    return;
                }
                finally
                {
                    sock3.Disconnect(false);
                }
            }
        }

        sock.Disconnect(false);
        Console.Read();

    }


    static string FTPRequest(string command, Socket sock)
    {
        string resp = string.Empty;
        Byte[] bytesReceived = new Byte[1024];
        int bytes = 0;

        Byte[] bytesSent = Encoding.ASCII.GetBytes(command);
        sock.Send(bytesSent, bytesSent.Length, 0);

        Thread.Sleep(1000);

        try
        {
            bytes = sock.Receive(bytesReceived, bytesReceived.Length, 0);
        }
        catch (Exception)
        {
        }
        return Encoding.ASCII.GetString(bytesReceived, 0, bytes);
    }

    static IPEndPoint IPEnd(string pasvResponse)
    {
        string s = pasvResponse.Split(' ')[4];
        s = s.Trim();
        s = s.Trim('(', ')');
        string[] sp = s.Split(',');
        IPHostEntry dns = new IPHostEntry();
        try
        {
            dns = Dns.Resolve(string.Format("{0}.{1}.{2}.{3}", sp[0], sp[1], sp[2], sp[3]));
        }
        catch (Exception)
        {
        }
        int port = int.Parse(sp[4]) * 256 + int.Parse(sp[5]);
        return new IPEndPoint(dns.AddressList[0], port);
    }

我对将 c# 用于 FTP 的东西有点陌生,所以非常感谢任何帮助。

4

1 回答 1

3

我建议直接使用FtpWebRequest从 FTP 服务器获取信息。它不太可能导致错误,因为它是核心框架中非常健壮的部分。

于 2011-04-06T15:53:20.677 回答