Avatar billede spyrodrag Nybegynder
12. oktober 2004 - 12:18 Der er 31 kommentarer og
1 løsning

arne_v fxp

Hej arne_v.

Du har givet mig følgende kode til et andet spørgsmål. Hvor mange points vil du have for at modificere koden til at sende filer fra server1-server2 uden at de bliver downloadet til clientens PC undervejs.

Tusind gange tak på forhånd.
Martin.

Kode:


Imports System
Imports System.IO
Imports System.Text
Imports System.Net.Sockets
Imports System.Threading

Public Class FtpClient
    Private ctrl As TcpClient
    Private ctrlstm As NetworkStream
    Private data As TcpClient
    Private datastm As NetworkStream

    Private Shared Sub Send(ByVal stm As NetworkStream, ByVal line As String)
        Dim b As Byte() = Encoding.Default.GetBytes(line)
        stm.Write(b, 0, b.Length)
    End Sub

    Private Shared Function Receive(ByVal stm As NetworkStream) As String
        Dim b(100000 - 1) As Byte
        Dim ix As Integer = 0
        Dim n As Integer
        While stm.DataAvailable
            n = stm.Read(b, ix, b.Length - ix)
            ix += n
        End While
        Return Encoding.Default.GetString(b, 0, ix)
    End Function

    Public Shared Function Command(ByVal stm As NetworkStream, ByVal cmd As String) As String
        Send(stm, cmd + Convert.ToChar(13) + Convert.ToChar(10))
        Thread.Sleep(50)
        Return Receive(stm)
    End Function

    Private Sub SetupData()
        Dim dataaddr As String = Command(ctrlstm, "PASV")
        Dim addrparts As String() = dataaddr.Split("()".ToCharArray)(1).Split(",".ToCharArray)
        Dim datahost As String = addrparts(0) + "." + addrparts(1) + "." + addrparts(2) + "." + addrparts(3)
        Dim dataport As Integer = Integer.Parse(addrparts(4)) * 256 + Integer.Parse(addrparts(5))
        data = New TcpClient (datahost, dataport)
        datastm = data.GetStream
    End Sub

    Public Sub New(ByVal host As String, ByVal username As String, ByVal password As String)
        ctrl = New TcpClient (host, 21)
        ctrlstm = ctrl.GetStream
        Command(ctrlstm, "USER " + username)
        Command(ctrlstm, "PASS " + password)
    End Sub

    Public Function Dir() As String
        SetupData
        Command(ctrlstm, "LIST")
        Dim res As String = Receive(datastm)
        Receive(ctrlstm)
        datastm.Close
        data.Close
        Return res
    End Function

    Public Function ShortDir() As String
        SetupData
        Command(ctrlstm, "NLST")
        Dim res As String = Receive(datastm)
        Receive(ctrlstm)
        datastm.Close
        data.Close
        Return res
    End Function

    Public Sub MkDir(ByVal dir As String)
        Command(ctrlstm, "MKD " + dir)
    End Sub

    Public Sub RmDir(ByVal dir As String)
        Command(ctrlstm, "RMD " + dir)
    End Sub

    Public Sub ChDir(ByVal dir As String)
        Command(ctrlstm, "CWD " + dir)
    End Sub

    Public Sub UpLoad(ByVal filename As String, ByVal binary As Boolean)
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "STOR " + filename)
        Receive(ctrlstm)
        Dim f As FileStream = New FileStream (filename, FileMode.Open)
        Dim b(100000 - 1) As Byte
        Dim ix As Integer = 0
        Dim n As Integer
        While ix < f.Length
            n = f.Read(b, 0, b.Length)
            datastm.Write(b, 0, n)
            Thread.Sleep(100)
            ix += n
        End While
        f.Close
        datastm.Close
        data.Close
    End Sub

    Public Sub DownLoad(ByVal filename As String, ByVal binary As Boolean)
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "RETR " + filename)
        Receive(ctrlstm)
        Dim f As FileStream = New FileStream (filename, FileMode.Create)
        Dim b(100000 - 1) As Byte
        Dim n As Integer
        While datastm.DataAvailable
            n = datastm.Read(b, 0, b.Length)
            f.Write(b, 0, n)
            Thread.Sleep(100)
        End While
        f.Close
        datastm.Close
        data.Close
    End Sub

    Public Function InitUpLoad(ByVal filename As String, ByVal binary As Boolean) As NetworkStream
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "STOR " + filename)
        Receive(ctrlstm)
        Return datastm
    End Function
 
    Public Sub EndUpload
        datastm.Close
        data.Close
    End Sub

    Public Function InitDownLoad(ByVal filename As String, ByVal binary As Boolean) As NetworkStream
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "RETR " + filename)
        Receive(ctrlstm)
        Return datastm
    End Function
 
    Public Sub EndDownload
        datastm.Close
        data.Close
    End Sub

    Public Sub Logout()
        Command(ctrlstm, "QUIT")
        ctrlstm.Close
        ctrl.Close
    End Sub
End Class

Public Class Fxp
    Public Shared Sub Transfer(fromhost As String, fromuser As String, frompass As String, _
                              path As String, filename As String, binary As Boolean, _
                              tohost As String, touser As String, topass As String)
        Dim fromcli As FtpClient = New FtpClient(fromhost, fromuser, frompass)
        Dim tocli As FtpClient = New FtpClient(tohost, touser, topass)
        fromcli.ChDir(path)
        tocli.ChDir(path)
        Dim istm As NetworkStream = fromcli.InitDownLoad(filename, binary)
        Dim ostm As NetworkStream = tocli.InitUpLoad("_" & filename, binary)
        Dim b(100000 - 1) As Byte
        Dim n As Integer
        While istm.DataAvailable
            n = istm.Read(b, 0, b.Length)
            ostm.Write(b, 0, n)
            Thread.Sleep(100)
        End While
        fromcli.EndDownLoad
        tocli.EndUpLoad
        fromcli.Logout
        tocli.Logout
    End Sub
End Class

Class TestClass
    Public Shared Sub Main(ByVal args As String())
        Fxp.Transfer("localhost", "anonymous", "arne@", ".", "z.zip", True, "localhost", "anonymous", "arne@")
    End Sub
End Class
Avatar billede arne_v Ekspert
12. oktober 2004 - 12:34 #1
Det er ikke tilladt at give mere end 200 point, så ...

:-)

Jeg kan godt prøve at kigge på det, men det bliver tidligst i morgen aften.
Avatar billede spyrodrag Nybegynder
12. oktober 2004 - 13:11 #2
Tusind tak...

Men jeg vil gerne oprette et nyt spørgsmål til dig, og give dig endnu 200.

Venlig hilsen,
Martin.
Avatar billede arne_v Ekspert
12. oktober 2004 - 13:46 #3
Man må heller ikke give mere end 200 point ved at oprette et spørgsmål
ekstra.

Men 200 er helt fint.

Problemet er at få løst opgaven !
Avatar billede spyrodrag Nybegynder
13. oktober 2004 - 08:28 #4
Forresten.

Jeg har testet den kode, som er postet øverst.
Jeg vil gerne have muligheden for at kalde koden med følgende parameter:
Fxp.Transfer(FraIP, FraPort, FraBrugernavn, FraPassword, FraPath, Filnavn, Binary, TilIP, TilPort, TilBrugernavn, TilPassword)

Endvidere har jeg fundet en fejl; når min fra server og til server IKKE er den samme, så crasher programmet. Dette crash sker her:
Dim addrparts As String() = dataaddr.Split("()".ToCharArray)(1).Split(",".ToCharArray)
som ligger under SetupData.

Venlig hilsen,
Martin.
Avatar billede spyrodrag Nybegynder
13. oktober 2004 - 08:29 #5
Jeg glemte at skrive at der også skulle kunne kaldes med en TilPath.
Fxp.Transfer(FraIP, FraPort, FraBrugernavn, FraPassword, FraPath, Filnavn, Binary, TilIP, TilPort, TilBrugernavn, TilPassword, TilPath)

Venlig hilsen,
Martin.
Avatar billede arne_v Ekspert
13. oktober 2004 - 13:28 #6
TilPath er nem at lave da FTPClient klassen har en ChDir metode.

Jeg er en lille smule skeptisk overfor port. Har du brug for at connecte
til FTP servere som ikke lytter på port 21 ?
Avatar billede arne_v Ekspert
13. oktober 2004 - 13:28 #7
Crashet må jeg lige kigge på i aften.
Avatar billede arne_v Ekspert
13. oktober 2004 - 23:03 #8
Her er så en version med topath og en fix for crash (lidt længere pause):

Imports System
Imports System.IO
Imports System.Text
Imports System.Net.Sockets
Imports System.Threading

Public Class FtpClient
    Private ctrl As TcpClient
    Private ctrlstm As NetworkStream
    Private data As TcpClient
    Private datastm As NetworkStream

    Private Shared Sub Send(ByVal stm As NetworkStream, ByVal line As String)
        Dim b As Byte() = Encoding.Default.GetBytes(line)
        stm.Write(b, 0, b.Length)
    End Sub

    Private Shared Function Receive(ByVal stm As NetworkStream) As String
        Dim b(100000 - 1) As Byte
        Dim ix As Integer = 0
        Dim n As Integer
        While stm.DataAvailable
            n = stm.Read(b, ix, b.Length - ix)
            ix += n
        End While
        Return Encoding.Default.GetString(b, 0, ix)
    End Function

    Public Shared Function Command(ByVal stm As NetworkStream, ByVal cmd As String) As String
        Send(stm, cmd + Convert.ToChar(13) + Convert.ToChar(10))
        Thread.Sleep(200)
        Return Receive(stm)
    End Function

    Private Sub SetupData()
        Dim dataaddr As String = Command(ctrlstm, "PASV")
        Dim addrparts As String() = dataaddr.Split("()".ToCharArray)(1).Split(",".ToCharArray)
        Dim datahost As String = addrparts(0) + "." + addrparts(1) + "." + addrparts(2) + "." + addrparts(3)
        Dim dataport As Integer = Integer.Parse(addrparts(4)) * 256 + Integer.Parse(addrparts(5))
        data = New TcpClient (datahost, dataport)
        datastm = data.GetStream
    End Sub

    Public Sub New(ByVal host As String, ByVal username As String, ByVal password As String)
        ctrl = New TcpClient (host, 21)
        ctrlstm = ctrl.GetStream
        Command(ctrlstm, "USER " + username)
        Command(ctrlstm, "PASS " + password)
    End Sub

    Public Function Dir() As String
        SetupData
        Command(ctrlstm, "LIST")
        Dim res As String = Receive(datastm)
        Receive(ctrlstm)
        datastm.Close
        data.Close
        Return res
    End Function

    Public Function ShortDir() As String
        SetupData
        Command(ctrlstm, "NLST")
        Dim res As String = Receive(datastm)
        Receive(ctrlstm)
        datastm.Close
        data.Close
        Return res
    End Function

    Public Sub MkDir(ByVal dir As String)
        Command(ctrlstm, "MKD " + dir)
    End Sub

    Public Sub RmDir(ByVal dir As String)
        Command(ctrlstm, "RMD " + dir)
    End Sub

    Public Sub ChDir(ByVal dir As String)
        Command(ctrlstm, "CWD " + dir)
    End Sub

    Public Sub UpLoad(ByVal filename As String, ByVal binary As Boolean)
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "STOR " + filename)
        Receive(ctrlstm)
        Dim f As FileStream = New FileStream (filename, FileMode.Open)
        Dim b(100000 - 1) As Byte
        Dim ix As Integer = 0
        Dim n As Integer
        While ix < f.Length
            n = f.Read(b, 0, b.Length)
            datastm.Write(b, 0, n)
            Thread.Sleep(100)
            ix += n
        End While
        f.Close
        datastm.Close
        data.Close
    End Sub

    Public Sub DownLoad(ByVal filename As String, ByVal binary As Boolean)
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "RETR " + filename)
        Receive(ctrlstm)
        Dim f As FileStream = New FileStream (filename, FileMode.Create)
        Dim b(100000 - 1) As Byte
        Dim n As Integer
        While datastm.DataAvailable
            n = datastm.Read(b, 0, b.Length)
            f.Write(b, 0, n)
            Thread.Sleep(100)
        End While
        f.Close
        datastm.Close
        data.Close
    End Sub

    Public Function InitUpLoad(ByVal filename As String, ByVal binary As Boolean) As NetworkStream
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "STOR " + filename)
        Receive(ctrlstm)
        Return datastm
    End Function

    Public Sub EndUpload
        datastm.Close
        data.Close
    End Sub

    Public Function InitDownLoad(ByVal filename As String, ByVal binary As Boolean) As NetworkStream
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "RETR " + filename)
        Receive(ctrlstm)
        Return datastm
    End Function

    Public Sub EndDownload
        datastm.Close
        data.Close
    End Sub

    Public Sub Logout()
        Command(ctrlstm, "QUIT")
        ctrlstm.Close
        ctrl.Close
    End Sub
End Class

Public Class Fxp
    Public Shared Sub Transfer(fromhost As String, fromuser As String, frompass As String, frompath As String, _
                              filename As String, binary As Boolean, _
                              tohost As String, touser As String, topass As String, topath As String)
        Dim fromcli As FtpClient = New FtpClient(fromhost, fromuser, frompass)
        Dim tocli As FtpClient = New FtpClient(tohost, touser, topass)
        fromcli.ChDir(frompath)
        tocli.ChDir(topath)
        Dim istm As NetworkStream = fromcli.InitDownLoad(filename, binary)
        Dim ostm As NetworkStream = tocli.InitUpLoad(filename, binary)
        Dim b(100000 - 1) As Byte
        Dim n As Integer
        While istm.DataAvailable
            n = istm.Read(b, 0, b.Length)
            ostm.Write(b, 0, n)
            Thread.Sleep(100)
        End While
        fromcli.EndDownLoad
        tocli.EndUpLoad
        fromcli.Logout
        tocli.Logout
    End Sub
End Class

Class TestClass
    Public Shared Sub Main(ByVal args As String())
        Fxp.Transfer("arne", "anonymous", "arne@", "utilities", "utilities.zip", True, "arne2", "anonymous", "arne@", ".")
    End Sub
End Class
Avatar billede arne_v Ekspert
13. oktober 2004 - 23:03 #9
Næste trin TransferDirect metoden !
Avatar billede arne_v Ekspert
13. oktober 2004 - 23:48 #10
Hm.

Jeg ved hvordan jeg vil lave det.

Men jeg sidder lige nu fast i en error code 501 ...
Avatar billede spyrodrag Nybegynder
14. oktober 2004 - 08:53 #11
Jeg glæder mig til at se løsningen! :)
Avatar billede arne_v Ekspert
14. oktober 2004 - 23:13 #12
Hm.

Det er som forhekset.

Gad vide om de FTP servere jeg tester på overhovedet understøtter det.
Avatar billede spyrodrag Nybegynder
15. oktober 2004 - 08:15 #13
jeg er ubeskrivelig glad for at du gider at bruge tid på det!
Avatar billede arne_v Ekspert
17. oktober 2004 - 22:47 #14
Jeg kan ikke finde nogle servere som tillader dette.

Nu har jeg testet det med client program + 2 x IIS localhost.

Så må du prøve om det virker med 2 rigtige FTP servere.
Avatar billede arne_v Ekspert
17. oktober 2004 - 22:47 #15
Imports System
Imports System.IO
Imports System.Text
Imports System.Net.Sockets
Imports System.Threading

Public Class FtpClient
    Private ctrl As TcpClient
    Private ctrlstm As NetworkStream
    Private data As TcpClient
    Private datastm As NetworkStream

    Private Shared Sub Send(ByVal stm As NetworkStream, ByVal line As String)
        Dim b As Byte() = Encoding.Default.GetBytes(line)
        stm.Write(b, 0, b.Length)
    End Sub

    Private Shared Function Receive(ByVal stm As NetworkStream) As String
        Dim b(100000 - 1) As Byte
        Dim ix As Integer = 0
        Dim n As Integer
        While stm.DataAvailable
            n = stm.Read(b, ix, b.Length - ix)
            ix += n
        End While
        Return Encoding.Default.GetString(b, 0, ix)
    End Function

    Public Shared Function Command(ByVal stm As NetworkStream, ByVal cmd As String) As String
        Send(stm, cmd + Convert.ToChar(13) + Convert.ToChar(10))
        Thread.Sleep(200)
        Return Receive(stm)
    End Function

    Private Sub SetupData()
        Dim dataaddr As String = Command(ctrlstm, "PASV")
        Dim addrparts As String() = dataaddr.Split("()".ToCharArray)(1).Split(",".ToCharArray)
        Dim datahost As String = addrparts(0) + "." + addrparts(1) + "." + addrparts(2) + "." + addrparts(3)
        Dim dataport As Integer = Integer.Parse(addrparts(4)) * 256 + Integer.Parse(addrparts(5))
        data = New TcpClient (datahost, dataport)
        datastm = data.GetStream
    End Sub

    Private Function SetupData1() As String
        Dim dataaddr As String = Command(ctrlstm, "PASV")
        Dim addrparts As String = dataaddr.Split("()".ToCharArray)(1)
        SetupData1 = addrparts
    End Function

    Private Sub SetupData2(ByVal addr As String)
        Command(ctrlstm, "PORT " + addr)
    End Sub

    Public Sub New(ByVal host As String, ByVal username As String, ByVal password As String)
        ctrl = New TcpClient (host, 21)
        ctrlstm = ctrl.GetStream
        Command(ctrlstm, "USER " + username)
        Command(ctrlstm, "PASS " + password)
    End Sub

    Public Function Dir() As String
        SetupData
        Command(ctrlstm, "LIST")
        Dim res As String = Receive(datastm)
        Receive(ctrlstm)
        datastm.Close
        data.Close
        Return res
    End Function

    Public Function ShortDir() As String
        SetupData
        Command(ctrlstm, "NLST")
        Dim res As String = Receive(datastm)
        Receive(ctrlstm)
        datastm.Close
        data.Close
        Return res
    End Function

    Public Sub MkDir(ByVal dir As String)
        Command(ctrlstm, "MKD " + dir)
    End Sub

    Public Sub RmDir(ByVal dir As String)
        Command(ctrlstm, "RMD " + dir)
    End Sub

    Public Sub ChDir(ByVal dir As String)
        Command(ctrlstm, "CWD " + dir)
    End Sub

    Public Sub UpLoad(ByVal filename As String, ByVal binary As Boolean)
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "STOR " + filename)
        Receive(ctrlstm)
        Dim f As FileStream = New FileStream (filename, FileMode.Open)
        Dim b(100000 - 1) As Byte
        Dim ix As Integer = 0
        Dim n As Integer
        While ix < f.Length
            n = f.Read(b, 0, b.Length)
            datastm.Write(b, 0, n)
            Thread.Sleep(100)
            ix += n
        End While
        f.Close
        datastm.Close
        data.Close
    End Sub

    Public Sub DownLoad(ByVal filename As String, ByVal binary As Boolean)
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "RETR " + filename)
        Receive(ctrlstm)
        Dim f As FileStream = New FileStream (filename, FileMode.Create)
        Dim b(100000 - 1) As Byte
        Dim n As Integer
        While datastm.DataAvailable
            n = datastm.Read(b, 0, b.Length)
            f.Write(b, 0, n)
            Thread.Sleep(100)
        End While
        f.Close
        datastm.Close
        data.Close
    End Sub

    Public Function InitUpLoad(ByVal filename As String, ByVal binary As Boolean) As NetworkStream
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "STOR " + filename)
        Receive(ctrlstm)
        Return datastm
    End Function

    Public Sub EndUpload
        datastm.Close
        data.Close
    End Sub

    Public Function InitDownLoad(ByVal filename As String, ByVal binary As Boolean) As NetworkStream
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "RETR " + filename)
        Receive(ctrlstm)
        Return datastm
    End Function

    Public Sub EndDownload
        datastm.Close
        data.Close
    End Sub

    Public Function InitDirectUpLoad(ByVal binary As Boolean) As String
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        InitDirectUpload = SetupData1
    End Function
   
    Public Sub DirectUpLoad(ByVal filename As String)
        Command(ctrlstm, "STOR " + filename)
        Receive(ctrlstm)
    End Sub

    Public Sub InitDirectDownLoad(ByVal addr As String, ByVal binary As Boolean)
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData2(addr)
    End Sub
   
    Public Sub DirectDownLoad(ByVal filename As String)
        Command(ctrlstm, "RETR " + filename)
        Receive(ctrlstm)
    End Sub

    Public Sub Logout()
        Command(ctrlstm, "QUIT")
        ctrlstm.Close
        ctrl.Close
    End Sub
End Class

Public Class Fxp
    Public Shared Sub Transfer(fromhost As String, fromuser As String, frompass As String, frompath As String, _
                              filename As String, binary As Boolean, _
                              tohost As String, touser As String, topass As String, topath As String)
        Dim fromcli As FtpClient = New FtpClient(fromhost, fromuser, frompass)
        Dim tocli As FtpClient = New FtpClient(tohost, touser, topass)
        fromcli.ChDir(frompath)
        tocli.ChDir(topath)
        Dim istm As NetworkStream = fromcli.InitDownLoad(filename, binary)
        Dim ostm As NetworkStream = tocli.InitUpLoad(filename, binary)
        Dim b(100000 - 1) As Byte
        Dim n As Integer
        While istm.DataAvailable
            n = istm.Read(b, 0, b.Length)
            ostm.Write(b, 0, n)
            Thread.Sleep(100)
        End While
        fromcli.EndDownLoad
        tocli.EndUpLoad
        fromcli.Logout
        tocli.Logout
    End Sub
    Public Shared Sub TransferDirect(fromhost As String, fromuser As String, frompass As String, frompath As String, _
                                    filename As String, binary As Boolean, _
                                    tohost As String, touser As String, topass As String, topath As String)
        Dim fromcli As FtpClient = New FtpClient(fromhost, fromuser, frompass)
        Dim tocli As FtpClient = New FtpClient(tohost, touser, topass)
        fromcli.ChDir(frompath)
        tocli.ChDir(topath)
        fromcli.InitDirectDownload(tocli.InitDirectUpload(binary), binary)
        fromcli.DirectDownload(filename)
        tocli.DirectUpload(filename)
        fromcli.Logout
        tocli.Logout
    End Sub
End Class

Class TestClass
    Public Shared Sub Main(ByVal args As String())
        Fxp.TransferDirect("localhost", "anonymous", "arne@", "d1", "test.txt", False, "localhost", "anonymous", "arne@", "d2")
    End Sub
End Class
Avatar billede spyrodrag Nybegynder
18. oktober 2004 - 09:06 #16
Imponerende...!
Sørger dette stykke kode for at filerne ikke kommer til at røre min PC?

Jeg har to ønsker til koden;
1) Det skal være muligt at kalde med en port værdi for hver server.
2) Support for flere filer

Venlig hilsen,
Martin.
Avatar billede arne_v Ekspert
18. oktober 2004 - 10:52 #17
Ja.

Men som sagt har jeg ikke kunnet testet den ordentligt.

re 1)

Det er ret nemt at tilføje.

re 2)

Er det ikke bare at kalde TransferDirect flere gange ?
Avatar billede arne_v Ekspert
18. oktober 2004 - 23:09 #18
Her er en med port:

Imports System
Imports System.IO
Imports System.Text
Imports System.Net.Sockets
Imports System.Threading

Public Class FtpClient
    Private ctrl As TcpClient
    Private ctrlstm As NetworkStream
    Private data As TcpClient
    Private datastm As NetworkStream

    Private Shared Sub Send(ByVal stm As NetworkStream, ByVal line As String)
        Dim b As Byte() = Encoding.Default.GetBytes(line)
        stm.Write(b, 0, b.Length)
    End Sub

    Private Shared Function Receive(ByVal stm As NetworkStream) As String
        Dim b(100000 - 1) As Byte
        Dim ix As Integer = 0
        Dim n As Integer
        While stm.DataAvailable
            n = stm.Read(b, ix, b.Length - ix)
            ix += n
        End While
        Return Encoding.Default.GetString(b, 0, ix)
    End Function

    Public Shared Function Command(ByVal stm As NetworkStream, ByVal cmd As String) As String
        Send(stm, cmd + Convert.ToChar(13) + Convert.ToChar(10))
        Thread.Sleep(200)
        Return Receive(stm)
    End Function

    Private Sub SetupData()
        Dim dataaddr As String = Command(ctrlstm, "PASV")
        Dim addrparts As String() = dataaddr.Split("()".ToCharArray)(1).Split(",".ToCharArray)
        Dim datahost As String = addrparts(0) + "." + addrparts(1) + "." + addrparts(2) + "." + addrparts(3)
        Dim dataport As Integer = Integer.Parse(addrparts(4)) * 256 + Integer.Parse(addrparts(5))
        data = New TcpClient (datahost, dataport)
        datastm = data.GetStream
    End Sub

    Private Function SetupData1() As String
        Dim dataaddr As String = Command(ctrlstm, "PASV")
        Dim addrparts As String = dataaddr.Split("()".ToCharArray)(1)
        SetupData1 = addrparts
    End Function

    Private Sub SetupData2(ByVal addr As String)
        Command(ctrlstm, "PORT " + addr)
    End Sub

    Public Sub New(ByVal host As String, ByVal username As String, ByVal password As String)
        ctrl = New TcpClient (host, 21)
        ctrlstm = ctrl.GetStream
        Command(ctrlstm, "USER " + username)
        Command(ctrlstm, "PASS " + password)
    End Sub

    Public Sub New(ByVal host As String, ByVal port As Integer, ByVal username As String, ByVal password As String)
        ctrl = New TcpClient (host, port)
        ctrlstm = ctrl.GetStream
        Command(ctrlstm, "USER " + username)
        Command(ctrlstm, "PASS " + password)
    End Sub

    Public Function Dir() As String
        SetupData
        Command(ctrlstm, "LIST")
        Dim res As String = Receive(datastm)
        Receive(ctrlstm)
        datastm.Close
        data.Close
        Return res
    End Function

    Public Function ShortDir() As String
        SetupData
        Command(ctrlstm, "NLST")
        Dim res As String = Receive(datastm)
        Receive(ctrlstm)
        datastm.Close
        data.Close
        Return res
    End Function

    Public Sub MkDir(ByVal dir As String)
        Command(ctrlstm, "MKD " + dir)
    End Sub

    Public Sub RmDir(ByVal dir As String)
        Command(ctrlstm, "RMD " + dir)
    End Sub

    Public Sub ChDir(ByVal dir As String)
        Command(ctrlstm, "CWD " + dir)
    End Sub

    Public Sub UpLoad(ByVal filename As String, ByVal binary As Boolean)
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "STOR " + filename)
        Receive(ctrlstm)
        Dim f As FileStream = New FileStream (filename, FileMode.Open)
        Dim b(100000 - 1) As Byte
        Dim ix As Integer = 0
        Dim n As Integer
        While ix < f.Length
            n = f.Read(b, 0, b.Length)
            datastm.Write(b, 0, n)
            Thread.Sleep(100)
            ix += n
        End While
        f.Close
        datastm.Close
        data.Close
    End Sub

    Public Sub DownLoad(ByVal filename As String, ByVal binary As Boolean)
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "RETR " + filename)
        Receive(ctrlstm)
        Dim f As FileStream = New FileStream (filename, FileMode.Create)
        Dim b(100000 - 1) As Byte
        Dim n As Integer
        While datastm.DataAvailable
            n = datastm.Read(b, 0, b.Length)
            f.Write(b, 0, n)
            Thread.Sleep(100)
        End While
        f.Close
        datastm.Close
        data.Close
    End Sub

    Public Function InitUpLoad(ByVal filename As String, ByVal binary As Boolean) As NetworkStream
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "STOR " + filename)
        Receive(ctrlstm)
        Return datastm
    End Function

    Public Sub EndUpload
        datastm.Close
        data.Close
    End Sub

    Public Function InitDownLoad(ByVal filename As String, ByVal binary As Boolean) As NetworkStream
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "RETR " + filename)
        Receive(ctrlstm)
        Return datastm
    End Function

    Public Sub EndDownload
        datastm.Close
        data.Close
    End Sub

    Public Function InitDirectUpLoad(ByVal binary As Boolean) As String
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        InitDirectUpload = SetupData1
    End Function
   
    Public Sub DirectUpLoad(ByVal filename As String)
        Command(ctrlstm, "STOR " + filename)
        Receive(ctrlstm)
    End Sub

    Public Sub InitDirectDownLoad(ByVal addr As String, ByVal binary As Boolean)
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData2(addr)
    End Sub
   
    Public Sub DirectDownLoad(ByVal filename As String)
        Command(ctrlstm, "RETR " + filename)
        Receive(ctrlstm)
    End Sub

    Public Sub Logout()
        Command(ctrlstm, "QUIT")
        ctrlstm.Close
        ctrl.Close
    End Sub
End Class

Public Class Fxp
    Public Shared Sub Transfer(fromhost As String, fromuser As String, frompass As String, frompath As String, _
                              filename As String, binary As Boolean, _
                              tohost As String, touser As String, topass As String, topath As String)
        Dim fromcli As FtpClient = New FtpClient(fromhost, fromuser, frompass)
        Dim tocli As FtpClient = New FtpClient(tohost, touser, topass)
        fromcli.ChDir(frompath)
        tocli.ChDir(topath)
        Dim istm As NetworkStream = fromcli.InitDownLoad(filename, binary)
        Dim ostm As NetworkStream = tocli.InitUpLoad(filename, binary)
        Dim b(100000 - 1) As Byte
        Dim n As Integer
        While istm.DataAvailable
            n = istm.Read(b, 0, b.Length)
            ostm.Write(b, 0, n)
            Thread.Sleep(100)
        End While
        fromcli.EndDownLoad
        tocli.EndUpLoad
        fromcli.Logout
        tocli.Logout
    End Sub
    Public Shared Sub TransferDirect(fromhost As String, fromport As Integer, fromuser As String, frompass As String, frompath As String, _
                                    filename As String, binary As Boolean, _
                                    tohost As String, toport As Integer, touser As String, topass As String, topath As String)
        Dim fromcli As FtpClient = New FtpClient(fromhost, fromport, fromuser, frompass)
        Dim tocli As FtpClient = New FtpClient(tohost, toport, touser, topass)
        fromcli.ChDir(frompath)
        tocli.ChDir(topath)
        fromcli.InitDirectDownload(tocli.InitDirectUpload(binary), binary)
        fromcli.DirectDownload(filename)
        tocli.DirectUpload(filename)
        fromcli.Logout
        tocli.Logout
    End Sub
End Class

Class TestClass
    Public Shared Sub Main(ByVal args As String())
        Fxp.TransferDirect("localhost", 21, "anonymous", "arne@", "d1", "test.txt", False, "localhost", 21, "anonymous", "arne@", "d2")
    End Sub
End Class
Avatar billede spyrodrag Nybegynder
19. oktober 2004 - 08:10 #19
Den kode du har lavet der er fantastisk.! og du fortjæner alle points og lidt til :)

Jeg har dog stadig nogle få ønsker; hvis jeg skal overføre flere filer, ved at kalde funktionen flere gange, så disconnecter den og forbinder igen, for hver fil. Er det muligt at gå ind og få fat i hvilke filer der ligger i 'frompath'? Det ville gøre det hele 100 gange så let. På den måde ville man vel kunne køre noget i stil med:

for each file in bla bla bla
  fromcli.DirectDownload(filename)
  tocli.DirectUpload(filename)
next file

Venlig hilsen,
Martin.
Avatar billede arne_v Ekspert
19. oktober 2004 - 22:47 #20
Public Shared Sub TransferDirect(fromhost As String, fromport As Integer, fromuser As String, frompass As String, frompath As String, _
                                    filename() As String, binary As Boolean, _
                                    tohost As String, toport As Integer, touser As String, topass As String, topath As String)
        Dim fromcli As FtpClient = New FtpClient(fromhost, fromport, fromuser, frompass)
        Dim tocli As FtpClient = New FtpClient(tohost, toport, touser, topass)
        fromcli.ChDir(frompath)
        tocli.ChDir(topath)
        Dim i As Integer
        For i = 0 To filename.Length
            fromcli.InitDirectDownload(tocli.InitDirectUpload(binary), binary)
            fromcli.DirectDownload(filename(i))
            tocli.DirectUpload(filename(i))
        Next
        fromcli.Logout
        tocli.Logout
    End Sub

tager et array som argument for filnavn (jeg er en lille smule skeptisk
overfor hvordan serverne vil håndtere det !).
Avatar billede arne_v Ekspert
19. oktober 2004 - 22:48 #21
Du kan bruge ShortDir funktionen til at få returneret de filer som er
i et directory (som en streng der kan parses).
Avatar billede arne_v Ekspert
19. oktober 2004 - 22:50 #22
og et svar
Avatar billede spyrodrag Nybegynder
20. oktober 2004 - 08:05 #23
Kanon!
Nu skal du høre; jeg arbejder for tiden på en IRC client, hvilket inkluderer: Activex, GUI, Access Database og nogle andre ting. Jeg har desværre nogle få problemer med koden, hvad skal du have for at optimere koden og rette nogle store fejl? Er det noget du er interesseret i?

Venlig hilsen,
Martin
Avatar billede spyrodrag Nybegynder
20. oktober 2004 - 13:47 #24
Jeg har efterhånden rodet lidt med den kode du gav mig, og er nu nået frem til løsningen...
Du er kommet til at bytte om på hvilken server der skal i port mode og hvilken server der skal i passive mode...
Løsningen:

'fromcli.InitDirectDownLoad(tocli.InitDirectUpLoad(binary), binary)
tocli.InitDirectDownLoad(fromcli.InitDirectUpLoad(binary), binary)

Venlig hilsen,
Martin
Avatar billede spyrodrag Nybegynder
20. oktober 2004 - 14:22 #25
En sidste ting...:
Er det ikke muligt at vente på at Fra og Til serveren har sagt at de er færdige med at downloade/uploade? Dette skal ske efter:

fromcli.DirectDownload(filename(i))
tocli.DirectUpload(filename(i))

Det er nødvendigt for at overføre filer der tager længere tid end det gør for koden at komme så langt.

Fra serveren siger: 226 Transfer ok
Til serveren siger: 226 File received ok.
Avatar billede arne_v Ekspert
20. oktober 2004 - 15:14 #26
ActiveX kender jeg intet til. GUI kender jeg lidt til. Databaser kender jeg meget til.

Snakker du om point eller kroner ?
Avatar billede arne_v Ekspert
20. oktober 2004 - 15:16 #27
Jeg var ikke klar over at der var krav til om det var fra eller til server som
skulle i PASV mode.
Avatar billede arne_v Ekspert
20. oktober 2004 - 15:17 #28
Det gælder sådan set alle kommandoerne. De burde ændres til at vente indtil status
findes fremfor bare at vente 200 millisekunder og så tage det der er.
Avatar billede spyrodrag Nybegynder
21. oktober 2004 - 09:18 #29
Det gælder sådan set alle kommandoerne. De burde ændres til at vente indtil status
findes fremfor bare at vente 200 millisekunder og så tage det der er.

<- har du en løsning på det? eller skal man lave noget 'rod' med en try, catch og prøve igen... det virker bare forkert at gøre det sådan...!

Snakker du om point eller kroner ?
lad os sige points i første omgang :)
Avatar billede arne_v Ekspert
23. oktober 2004 - 23:51 #30
Det skal ikke laves med try catch.

Men hver kommando der sendes skal vente på et svar.

Jeg kan godt lave det.

Men vi beynder at bevæge os fra klassisk Eksperten hjælp til selvhjælp over
i regulær software udvikling.

Hvis jeg kommer til at kede mig en dag kunne jeg godt finde på at lave det, men
jeg vil ikke garantere noget.

Hvis det haster så kan du selv lave det. Det er bare en masse nørklen for
at gøre koden mere robust, teste for status koder, udskrive fejlmeddelelser
og den slags.
Avatar billede spyrodrag Nybegynder
25. oktober 2004 - 08:26 #31
Jeg kan godt lave det.
<- Kan du løse det med at koden skal vente på at serveren er klar?

Det med at du ville kigge på det andet program, hvis du engang keder dig, det lyder helt okay!
Avatar billede spyrodrag Nybegynder
25. oktober 2004 - 08:28 #32
Vil du have min email, så jeg kan sende dig projectet?
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
Kurser inden for grundlæggende programmering

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