Avatar billede tigertool Nybegynder
27. januar 2005 - 22:07 Der er 49 kommentarer og
1 løsning

Simpel FTP Klient

Jeg ville høre om der er nogen der har en FTP Klient klasse liggende. Jeg havde tænkt mig noget lignende:

public class FTPClient
{
    //Opretter en forbindelse til FTPServeren
    public FTPClient(string host, string username, string password)
    {
    }

    //Downloader en fil eks. Download("test\\mappe\\fil.txt", "C:\\test\\fil.txt")
    public void Download(string serverFile, string localFile)
    {
    }

    //Uploader en fil eks. Upload("C:\\test\\fil.txt", "test\\mappe\\fil.txt")
    public void Upload(string localFile, string serverFile)
    {
    }

    //Opretter en mappe
    public void MkDir(string dirname)
    {
    }

    //Ændre mappe
    public void ChangeDir(string dirname)
    {
    }

    //Returnerer alle filer i mappen
    public string[] ListDir(string dirname)
    {
    }

    //Afbryder forbindelse
    public void Close()
    {
    }
}

Er der nogen der har det? Eller evt. kan bidrage med lidt info?
Avatar billede tigertool Nybegynder
27. januar 2005 - 22:09 #1
FTP Forbindelsen skal arbejde i en tråd, således at denne klasse kan arbejde uafhængigt af andre enheder.
Avatar billede arne_v Ekspert
27. januar 2005 - 22:10 #2
using System;
using System.IO;
using System.Text;
using System.Net.Sockets;
using System.Threading;

public class FtpClient
{
    private TcpClient ctrl;
    private NetworkStream ctrlstm;
    private TcpClient data;
    private NetworkStream datastm;
    private static void Send(NetworkStream stm, string line)
    {
        byte[] b = Encoding.Default.GetBytes(line);
        stm.Write(b, 0, b.Length);
    }
    private static string Receive(NetworkStream stm)
    {
        byte[] b = new byte[100000];
        int ix = 0;
        int n;
        while(stm.DataAvailable)
        {
            n = stm.Read(b, ix, b.Length - ix);
            ix += n;
        }
        return Encoding.Default.GetString(b, 0, ix);
    }
    public static string Command(NetworkStream stm, string cmd)
    {
        Send(stm, cmd + "\r\n");
        Thread.Sleep(50);
        return Receive(stm);
    }
    private void SetupData()
    {
        string dataaddr = Command(ctrlstm, "PASV");
        string[] addrparts = dataaddr.Split("()".ToCharArray())[1].Split(",".ToCharArray());
        string datahost = addrparts[0] + "." + addrparts[1] + "." + addrparts[2] + "." + addrparts[3];
        int dataport = int.Parse(addrparts[4]) * 256 + int.Parse(addrparts[5]);
        data = new TcpClient(datahost, dataport);
        datastm = data.GetStream();
    }
    public FtpClient(string host, string username, string password)
    {
        ctrl = new TcpClient(host, 21); 
        ctrlstm = ctrl.GetStream();
        Command(ctrlstm, "USER " + username);
        Command(ctrlstm, "PASS " + password);
    }
    public string Dir()
    {
        SetupData();
        Command(ctrlstm, "LIST");
        string res = Receive(datastm);
        Receive(ctrlstm);
        datastm.Close();
        data.Close();
        return res;
    }
    public string ShortDir()
    {
        SetupData();
        Command(ctrlstm, "NLST");
        string res = Receive(datastm);
        Receive(ctrlstm);
        datastm.Close();
        data.Close();
        return res;
    }
    public void MkDir(string dir)
    {
        Command(ctrlstm, "MKD " + dir);
    }
    public void RmDir(string dir)
    {
        Command(ctrlstm, "RMD " + dir);
    }
    public void ChDir(string dir)
    {
        Command(ctrlstm, "CWD " + dir);
    }
    public void UpLoad(string filename, bool binary)
    {
        if(binary)
        {
            Command(ctrlstm, "TYPE I");
        }
        else
        {
            Command(ctrlstm, "TYPE A");
        }
        SetupData();
        Command(ctrlstm, "STOR " + filename);
        Receive(ctrlstm);
        FileStream f = new FileStream(filename, FileMode.Open);
        byte[] b = new byte[100000];
        int ix = 0;
        int n;
        while(ix < f.Length)
        {
            n = f.Read(b, 0, b.Length);
            datastm.Write(b, 0, n);
            Thread.Sleep(100);
            ix += n;
        }
        f.Close();
        datastm.Close();
        data.Close();
    }
    public void DownLoad(string filename, bool binary)
    {
        if(binary)
        {
            Command(ctrlstm, "TYPE I");
        }
        else
        {
            Command(ctrlstm, "TYPE A");
        }
        SetupData();
        Command(ctrlstm, "RETR " + filename);
        Receive(ctrlstm);
        FileStream f = new FileStream(filename, FileMode.Create);
        byte[] b = new byte[100000];
        int n;
        while(datastm.DataAvailable)
        {
            n = datastm.Read(b, 0, b.Length);
            f.Write(b, 0, n);
            Thread.Sleep(100);
        }
        f.Close();
        datastm.Close();
        data.Close();
    }
    public void Logout()
    {
        Command(ctrlstm, "QUIT");
        ctrlstm.Close();
        ctrl.Close();
    }
}

class TestClass
{
    public static void Main(string[] args)
    {
        FtpClient cli = new FtpClient("localhost", "anonymous", "arne@");
        Console.WriteLine(cli.ShortDir());
        Console.WriteLine(cli.Dir());
        Directory.SetCurrentDirectory("C:\\");
        cli.DownLoad("z.zip", true);
        cli.MkDir("subdir");
        cli.ChDir("subdir");
        cli.UpLoad("z.zip", true);
        cli.Logout();
    }
}
Avatar billede arne_v Ekspert
27. januar 2005 - 22:11 #3
(jeg har lidt ekstra funktionalitet liggende i VB.NET som nemt kan backportes til C#)
Avatar billede arne_v Ekspert
27. januar 2005 - 22:12 #4
Avatar billede tigertool Nybegynder
27. januar 2005 - 22:12 #5
Jeg tester lige.
Avatar billede tigertool Nybegynder
27. januar 2005 - 22:20 #6
arne_v << jeg kunne godt tænke mig et par kommentarer i sourcen :)
Avatar billede tigertool Nybegynder
27. januar 2005 - 22:22 #7
Når jeg benytter:
Console.WriteLine(cli.ShortDir());
Console.WriteLine(cli.Dir());

Så får jeg en IndexOutOfBounds Exception.
Avatar billede arne_v Ekspert
27. januar 2005 - 22:24 #8
Sandsyneligvis fordi din login fejler
Avatar billede tigertool Nybegynder
27. januar 2005 - 22:24 #9
Nej, for jeg kan sagtens: cli.MkDir("subdir");
Avatar billede arne_v Ekspert
27. januar 2005 - 22:25 #10
Hvilken del af koden er ikke umiddelbart forståelig ?
Avatar billede tigertool Nybegynder
27. januar 2005 - 22:25 #11
og har tjekket på serveren. Mappen er oprettet.
Avatar billede arne_v Ekspert
27. januar 2005 - 22:26 #12
Prøv at sætte Sleep i Command metoden lidt op så f.eks. til 200
Avatar billede tigertool Nybegynder
27. januar 2005 - 22:26 #13
(http://www.csharphelp.com/archives/archive9.html) -- Prøvede jeg faktisk før jeg oprettede dette spm. Jeg kunne kun få det til at lykkes af og til. Ofte hang det ved oprettelse af forbindelse.
Avatar billede arne_v Ekspert
27. januar 2005 - 22:28 #14
Er det en langsom FTP server du skal have fat i ?
Avatar billede tigertool Nybegynder
27. januar 2005 - 22:31 #15
Det med Sleep hjalp ikke.
Jeg forsøger at connecte til en ProFTPd på en Debian maskine. Hvis jeg benytter en anden klient her på min PC så går det hurtigt.
Avatar billede tigertool Nybegynder
27. januar 2005 - 22:32 #16
Det sjove med FTPFactory er at det er rimelig langsomt, og det kun er af og til at der bliver oprettet forbindelse. Meget mystisk.
Avatar billede arne_v Ekspert
27. januar 2005 - 22:35 #17
Supporterer din FTP server PASV mode ?

Fordi min kode virker kun med PASV !
Avatar billede tigertool Nybegynder
27. januar 2005 - 22:36 #18
Det gør den, ja.
Avatar billede arne_v Ekspert
27. januar 2005 - 22:52 #19
Så må du jo nok til at debugge lidt.

    public static string Command(NetworkStream stm, string cmd)
    {
Console.WriteLine("SEND: " + cmd);
        Send(stm, cmd + "\r\n");
        Thread.Sleep(50);
        string resp = Receive(stm);
Console.WriteLine("RECV: " + resp);
        return resp;
    }
Avatar billede lifo Nybegynder
27. januar 2005 - 22:53 #20
har du prøvet edtFTPnet
http://www.enterprisedt.com/index.html

den har jeg gode erfaringe med
Avatar billede tigertool Nybegynder
27. januar 2005 - 22:58 #21
arne << jeg debugger i morgen. Jeg vender tilbage. Tak for nu.
Avatar billede arne_v Ekspert
30. januar 2005 - 19:39 #22
Kommet videre ?
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:08 #23
Ja. Jeg kan virkelig ikke få det til at virke. Jeg har debugget og debugget. Forstår det ikke. Jeg har også prøvet sourcen fra de url du smed. En af dem (http://www.csharphelp.com/archives/archive9.html) kan jeg nogle gange få til at virke. Andre gange står den bare og 'hænger' jeg kan se på min ftp server at der er forbindelse men at klienten er IDLE, selvom jeg har sat den til at uploade en stor fil. Og filen findes ikke på serveren. :( I'm lost.
Avatar billede arne_v Ekspert
01. februar 2005 - 22:10 #24
Kan du copy paste outpyt fra mit 27/01-2005 22:52:46 forslag, så kan jeg muligvis
sige noget ?
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:17 #25
SEND: USER krogh
RECV:
SEND: PASS ****** (Har jeg fjernet :P )
RECV:
SEND: TYPE I
RECV:
SEND: PASV
RECV:

Herefter kommer følgende:
Project Project12.exe encountered unhandled exception class System.IndexOutOfRangeException. Process stopped. Use Step or Run to continue.
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:20 #26
Jeg har lige prøvet at udfører de 4 kommandoer ved brug af telnet til ftp serveren. Der får jeg ingen fejl.
Avatar billede arne_v Ekspert
01. februar 2005 - 22:21 #27
Får du et svar ?

Der er jo ikke noget svar fra serveren i ovenstående !
Avatar billede arne_v Ekspert
01. februar 2005 - 22:22 #28
Prøv:

    public FtpClient(string host, string username, string password)
    {
        ctrl = new TcpClient(host, 21);
        ctrlstm = ctrl.GetStream();
        Thread.Sleep(250);
        Command(ctrlstm, "USER " + username);
        Command(ctrlstm, "PASS " + password);
        Thread.Sleep(250);
    }
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:25 #29
Jeg får ikke noget svar når jeg bruger sourcen, nej.

Men nu oprettes forbindelsen.

Hvordan tester jeg så om den kan downloade en given fil til mit drev E.

F.eks. har jeg irfan.exe liggende i roden af min ftp konto.
Avatar billede arne_v Ekspert
01. februar 2005 - 22:28 #30
Directory.SetCurrentDirectory("E:\\");
        cli.DownLoad("irfan.exe", true);

formoder jeg
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:28 #31
Jeg prøvede lige at lave en: Console.WriteLine(cli.Dir());
Der fik jeg så igen min Exception.
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:30 #32
-- gav også samme exception.
Avatar billede arne_v Ekspert
01. februar 2005 - 22:30 #33
Hvilken Sleep tid kører du med i Command ?
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:33 #34
200
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:35 #35
Kan det hjælpe dig hvis jeg opretter en konto på min ftp server til dig?
Avatar billede arne_v Ekspert
01. februar 2005 - 22:36 #36
måske ja
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:39 #37
IP: 212.242.201.104 brugernavn: arne_v :: PASSWORD: dit brugernavn
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:41 #38
Jeg benytter desuden C#Builder Personal fra borland.
Avatar billede arne_v Ekspert
01. februar 2005 - 22:48 #39
Jeg prøver lige.

Jeg har også en C#Builder installeret omend jeg ikke bruger den meget.
Avatar billede arne_v Ekspert
01. februar 2005 - 22:52 #40
Jeg kan lave en ShortDir og Dir men der ligger ingen filer ...
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:54 #41
Nej. Mappen er tom.

FtpClient cli = new FtpClient("10.0.0.200", "arne_v", "arne_v");
Console.WriteLine(cli.ShortDir());
Console.WriteLine(cli.Dir());

Har jeg lige prøvet. Lykkes ikke for mig. Jeg får den der exception.
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:55 #42
Kan du evt poste den source du lige benyttede?
Avatar billede tigertool Nybegynder
01. februar 2005 - 22:58 #43
Behøves ikke. Har vist fundet fejlen.
Avatar billede arne_v Ekspert
01. februar 2005 - 22:58 #44
using System;
using System.IO;
using System.Text;
using System.Net.Sockets;
using System.Threading;

public class FtpClient
{
    private TcpClient ctrl;
    private NetworkStream ctrlstm;
    private TcpClient data;
    private NetworkStream datastm;
    private static void Send(NetworkStream stm, string line)
    {
        byte[] b = Encoding.Default.GetBytes(line);
        stm.Write(b, 0, b.Length);
    }
    private static string Receive(NetworkStream stm)
    {
        byte[] b = new byte[100000];
        int ix = 0;
        int n;
        while(stm.DataAvailable)
        {
            n = stm.Read(b, ix, b.Length - ix);
            ix += n;
        }
        return Encoding.Default.GetString(b, 0, ix);
    }

    public static string Command(NetworkStream stm, string cmd)
    {
Console.WriteLine("SEND: " + cmd);
        Send(stm, cmd + "\r\n");
        Thread.Sleep(200);
        string resp = Receive(stm);
Console.WriteLine("RECV: " + resp);
        return resp;
    }
    private void SetupData()
    {
        string dataaddr = Command(ctrlstm, "PASV");
        string[] addrparts = dataaddr.Split("()".ToCharArray())[1].Split(",".ToCharArray());
        string datahost = addrparts[0] + "." + addrparts[1] + "." + addrparts[2] + "." + addrparts[3];
        int dataport = int.Parse(addrparts[4]) * 256 + int.Parse(addrparts[5]);
        data = new TcpClient(datahost, dataport);
        datastm = data.GetStream();
    }
    public FtpClient(string host, string username, string password)
    {
        ctrl = new TcpClient(host, 21);
        ctrlstm = ctrl.GetStream();
        Command(ctrlstm, "USER " + username);
        Command(ctrlstm, "PASS " + password);
    }
    public string Dir()
    {
        SetupData();
        Command(ctrlstm, "LIST");
        string res = Receive(datastm);
        Receive(ctrlstm);
        datastm.Close();
        data.Close();
        return res;
    }
    public string ShortDir()
    {
        SetupData();
        Command(ctrlstm, "NLST");
        string res = Receive(datastm);
        Receive(ctrlstm);
        datastm.Close();
        data.Close();
        return res;
    }
    public void MkDir(string dir)
    {
        Command(ctrlstm, "MKD " + dir);
    }
    public void RmDir(string dir)
    {
        Command(ctrlstm, "RMD " + dir);
    }
    public void ChDir(string dir)
    {
        Command(ctrlstm, "CWD " + dir);
    }
    public void UpLoad(string filename, bool binary)
    {
        if(binary)
        {
            Command(ctrlstm, "TYPE I");
        }
        else
        {
            Command(ctrlstm, "TYPE A");
        }
        SetupData();
        Command(ctrlstm, "STOR " + filename);
        Receive(ctrlstm);
        FileStream f = new FileStream(filename, FileMode.Open);
        byte[] b = new byte[100000];
        int ix = 0;
        int n;
        while(ix < f.Length)
        {
            n = f.Read(b, 0, b.Length);
            datastm.Write(b, 0, n);
            Thread.Sleep(100);
            ix += n;
        }
        f.Close();
        datastm.Close();
        data.Close();
    }
    public void DownLoad(string filename, bool binary)
    {
        if(binary)
        {
            Command(ctrlstm, "TYPE I");
        }
        else
        {
            Command(ctrlstm, "TYPE A");
        }
        SetupData();
        Command(ctrlstm, "RETR " + filename);
        Receive(ctrlstm);
        FileStream f = new FileStream(filename, FileMode.Create);
        byte[] b = new byte[100000];
        int n;
        while(datastm.DataAvailable)
        {
            n = datastm.Read(b, 0, b.Length);
            f.Write(b, 0, n);
            Thread.Sleep(100);
        }
        f.Close();
        datastm.Close();
        data.Close();
    }
    public void Logout()
    {
        Command(ctrlstm, "QUIT");
        ctrlstm.Close();
        ctrl.Close();
    }
}

class TestClass
{
    public static void Main(string[] args)
    {
        FtpClient cli = new FtpClient("212.242.201.104", "arne_v", "arne_v");
        Console.WriteLine(cli.ShortDir());
        Console.WriteLine(cli.Dir());
        cli.Logout();
    }
}
Avatar billede arne_v Ekspert
01. februar 2005 - 22:59 #45
SEND: USER arne_v
RECV: 220 ProFTPD 1.2.5rc1 Server (Net4all.dk) [net4all]
331 Password required for arne_v.

SEND: PASS arne_v
RECV: 230 User arne_v logged in.

SEND: PASV
RECV: 227 Entering Passive Mode (212,242,201,104,108,24)

SEND: NLST
RECV: 550 No files found.


SEND: PASV
RECV: 227 Entering Passive Mode (212,242,201,104,108,25)

SEND: LIST
RECV: 150 Opening ASCII mode data connection for file list
226-Transfer complete.
226 Quotas off


SEND: QUIT
RECV: 221 Goodbye.
Avatar billede arne_v Ekspert
01. februar 2005 - 22:59 #46
OK - så du har også hul igennem nu ?
Avatar billede tigertool Nybegynder
01. februar 2005 - 23:01 #47
Jep. Jeg prøvede bare for sjov at bruge min eksterne IP i stedet for min interne. Jeg kan kun bruge min eksterne. (Dog har jeg lige forsøgt med et FTP program at benytte den interne ip, det lykkes fint).

Smid et svar - du fortjener point :)
Avatar billede arne_v Ekspert
01. februar 2005 - 23:02 #48
ok
Avatar billede arne_v Ekspert
01. februar 2005 - 23:04 #49
Jeg skal understrege at min kode er ikke production quality. Den viser hvordan
man gør. Diverse fejl håndtering skal ligges ind for at den bliver robust.
Avatar billede tigertool Nybegynder
01. februar 2005 - 23:05 #50
Jep. Bl.a. hvis man forsøger at hente / sende en fil der ikke findes :)

Tak for hjælpen.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester