Creating an FTP Application Step by Step


To test this application (and the project), you need an FTP server. If you are connected to the Internet, you can use a number of FTP servers that allow anonymous access. These servers normally allow you to download files but not upload files. Alternatively, you can use a local FTP server found in Windows 2000 Server. The following sections start with installing and configuring an FTP server and then continue with a simple FTP client application.

Installing and Configuring an FTP Server in Windows 2000 Server

If you have access to Windows 2000 Server, you are in luck. One of the programs you can install is an FTP server. If it is already installed, you can configure it through the Internet Service Manager whose applet can be found in Administrative Tools in the Control Panel. If it is not yet installed, it is now time to do so.

To install the FTP Server in Windows 2000 Server, follow these steps:

  1. Double-click Add/Remove Programs from Control Panel.

  2. Click the Add/Remove Windows Components button on the left side of the page. The Windows Components Wizard will display. One of the items displayed in the Components list is Internet Information Services (IIS). Click this item.

  3. Click the Details button. The Internet Information Services dialog box shows.

  4. Check the File Transfer Protocol (FTP) Server subcomponent.

  5. Click the OK button and follow the instructions to install. You will be asked to insert the Windows 2000 Server installation CD.

The main task in the configuration is to map the directory that will become the root of the FTP server. In addition, you can also set the session timeout and the directory list style. Any user who has access to the Windows 2000 server will have the same access to the FTP server.

To configure the FTP server, follow these steps:

  1. Double-click Administrative Tools from Control Panel.

  2. Double-click the Internet Service Manager icon. You should be able to see the Default FTP Site icon under the machine name.

  3. Right-click the Default FTP Site icon and click Properties. The Default FTP Site Properties dialog box will display.

  4. Click the Home Directory tab, as shown in Figure 5-1.

  5. In the FTP Site Directory section, browse to the directory that you want to be the root of the FTP server.

  6. In the FTP Site Directory section, make sure that the Read and Write check boxes are selected.

  7. Select UNIX in the Directory Listing Style section.

  8. Click the Apply button and then the OK button.

click to expand
Figure 5-1: The Home Directory tab of the Default FTP Site Properties dialog box

Using the NETFTP Application

The NETFTP console application is a simple FTP client application that is similar to the ftp.exe program you can find in Unix/Linux or Windows. It consists of a class, NETFTP, that you can find in the Listings/Ch05/Other/NETFTP.vb file. The main purpose of this small application is to show how to use the System.Net.Sockets.Socket class to connect to an FTP server and do file transfer; it does not worry too much about error handling. After understanding this application, you can understand the project more easily.

To compile this program, type the following command in the command prompt:

 vbc -r:System.dll FTPNET.vb 

The result is an executable called FTPNET.exe.

The first thing to do to use this program is connect to an FTP server by typing the following:

 NETFTP <server> <user name> <password> 

If the connection attempt was successful, a message such as the following will display in the console.

 Connected. Waiting for reply... 220 bulbul Microsoft FTP Service (Version 5.0). USER Administrator 331 Password required for Administrator. PASS 230 User Administrator logged in. 215 Windows_NT version 5.0 200 Type set to A. 

If the connection failed, an error message will display.

Once connected, you will see the NETFTP> prompt. You can type one of the following commands in this prompt: CWD, DELE, LIST, PWD, QUIT, RETR, STOR. Upon execution, the server sends a reply that will display on the console. Other than that, the program outputs the "Command Invalid" message.

Upon successful execution of a command, the program displays the NETFTP> prompt again, indicating it is ready to accept a new command.

The valid commands are explained in the following sections.

CWD

This command causes the program to send a CWD command to the FTP server. This command changes the remote working directory. The syntax of this command is as follows:

 CWD directory 

where directory is the name of the directory to which you want to change. For example, to change the working directory to the /files/program directory, type the following:

 CWD /files/program 

You can also pass a relative path as the argument. To change to the parent directory of the current directory, type the following:

 CWD .. 

If the command successfully executes, the server sends the following message, which displays on the console:

 250 CWD command successful. 

If it cannot find the destination directory, the server sends the following message:

 550 /prog/images: The system cannot find the file specified. 

DELE

This command causes the application to send a DELE command to the connected FTP server. The DELE command deletes a file in the server. The syntax of this command is as follows:

 DELE pathToFileToDelete 

LIST

This command does not take an argument. It causes the application to send a LIST command to the server. The LIST command displays the content of the current directory. For example, the following is the output of the LIST directory:

 227 Entering Passive Mode (127,0,0,1,6,77). 125 Data connection already open; Transfer starting. 226 Transfer complete. drwxrwxrwx   1 owner    group        0 Jul 28 21:30 April2001 -rwxrwxrwx   1 owner    group   344064 Jul 29 13:25 Chapter5.doc -rwxrwxrwx   1 owner    group    12118 Jul 29 13:25 complete.wav -rwxrwxrwx   1 owner    group    12118 Jul 30 10:05 complete2.wav -rwxrwxrwx   1 owner    group     1050 Jul 29 13:25 Folder.gif -rwxrwxrwx   1 owner    group    53248 Jul 28 20:08 FTPClient.exe drwxrwxrwx   1 owner    group        0 Jul 28 20:21 June 2002 -rwxrwxrwx   1 owner    group     9216 Jul 30 10:02 NETFTP.exe -rwxrwxrwx   1 owner    group    12077 Jul 30 10:02 NETFTP.vb drwxrwxrwx   1 owner    group        0 Jul 30 10:05 New Folder drwxrwxrwx   1 owner    group        0 Jul 26 20:09 New Folder (2) -rwxrwxrwx   1 owner    group   132717 Jul 29 13:24 rfc959.txt 

Note that this directory listing is in the Unix style. An FTP server can choose to use another style.

PWD

The PWD command causes the application to send a PWD command to the FTP server. The PWD command displays the current directory. This command does not take an argument. On successful execution, this is an example of what the server may send:

 257 "/" is current directory. 

QUIT

The QUIT command causes the application to send a QUIT command to the FTP server. The QUIT command causes the connection to be closed. This command does not take an argument.

RETR

The RETR command causes the application to send a RETR command to the FTP server. The RETR command downloads a file from the server. The syntax of this command is as follows:

 RETR pathToFileToDownload 

STOR

The STOR command causes the application to send a STOR command to the FTP server. The STOR command uploads a file in the local directory. The syntax of this command is as follows:

 STOR pathToFileToUpload 

How the NETFTP Program Works

The NETFTP program comprises one class: NETFTP. The following sections describe the NETFTP class.

Declarations

The following is the declarations part of the NETFTP class:

 Private port As Integer = 21 Private controlSocket As _   New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) Private dataSocket As Socket Private serverAddress As String Public replyMessage As String Public replyCode As String 

Note that there are two Socket object references used in this class: control-Socket and dataSocket.

Methods

The following are the methods in the NETFTP class.

Connect

The Connect method connects to an FTP server (see Listing 5-1).

Listing 5-1: The Connect Method

start example
 Public Sub Connect(ByVal server As String)   Try     controlSocket.Connect(New     IPEndPoint(Dns.Resolve(server).AddressList(0), port))   Catch e As Exception     Console.WriteLine(e.ToString())     Return   End Try   If controlSocket.Connected Then     Console.WriteLine("Connected. Waiting for reply...")     GetResponse()   Else     Console.WriteLine("Couldn't connect.")   End If End Sub 
end example

The Connect method uses the controlSocket's Connect method to connect to an FTP server:

 Try   controlSocket.Connect(New IPEndPoint(Dns.Resolve(server).AddressList(0), port)) Catch e As Exception   Console.WriteLine(e.ToString())   Return End Try 

If the connection attempt is successful, the controlSocket's Connected property will be set to True. In this case, a message prints on the console and the GetResponse method is invoked:

 If controlSocket.Connected Then   Console.WriteLine("Connected. Waiting for reply...")   GetResponse() 

Otherwise, a "Couldn't connect" message displays on the console:

 Else   Console.WriteLine("Couldn't connect.") End If 

PassiveData

The PassiveData method sends the PASV command to the connected FTP server to make the server become passive (see Listing 5-2).

Listing 5-2: The PassiveData Method

start example
 Private Sub PassiveDataConnection()   SendCommand("PASV" & ControlChars.CrLf)   GetResponse()   Dim addr As String = replyMessage   addr = addr.Substring(addr.IndexOf("("c) + 1, _     addr.IndexOf(")"c) - addr.IndexOf("("c) - 1)   Dim address As String() = addr.Split(","c)   Dim ip As String = address(0) & "." & address(1) & "." & address(2) & "." & _     address(3)   Dim port As Integer = Convert.ToInt32(address(4)) * 256 + _     Convert.ToInt32(address(5))   dataSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream,     ProtocolType.Tcp)   dataSocket.Connect(New IPEndPoint(IPAddress.Parse(ip), port)) End Sub 
end example

If the PASV command successfully executes at the server, the server sends the address and port number of the data connection for the client to connect. Therefore, on a successful execution of PASV, the server replies by sending a string of the following format:

 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2). 

where a1, a2, a3, and a4 are parts of an IP address in dotted-quad notation, and p1 and p2 signify the port number. Consequently, you can obtain the IP address using the following lines:

 Dim addr As String = replyMessage addr = addr.Substring(addr.IndexOf("("c) + 1, addr.IndexOf(")"c) - addr.IndexOf("("c) - 1) Dim address As String() = addr.Split(","c) Dim ip As String = address(0) & "." & address(1) & "." & address(2) & "." & address(3) 

You obtain the port number by multiplying p1 with 256 and adding the result to p2:

 Dim port As Integer = Convert.ToInt32(address(4)) * 256 + Convert.ToInt32(address(5)) 

Then, you instantiate a data socket and invoke its Connect method:

 dataSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, _   ProtocolType.Tcp) dataSocket.Connect(New IPEndPoint(IPAddress.Parse(ip), port)) 

After the Connect method is called, the data socket is readily available to the method that invokes the PassiveData method.

GetResponse

The GetResponse method receives the byte stream from the connected FTP server. This method is invoked immediately after an FTP command is sent to the server (see Listing 5-3).

Listing 5-3: The GetResponse Method

start example
 Private Sub GetResponse()   ' this method listens for the server response and receives all bytes   ' sent by the server   ' A server response can be single line or multiline.   ' If the fourth byte of the first line is a hyphen, then it is   ' multiline. If multiline, waits until the line that starts with the   ' response code (the first three bytes of the first line).   Dim bytes(511) As Byte ' an array of 512 bytes   Dim receivedByteCount As Integer   Dim response As String = ""   ' get the first line   receivedByteCount = controlSocket.Receive(bytes)   response = Encoding.ASCII.GetString(bytes, 0, receivedByteCount)   Dim multiline As Boolean = (response.Chars(3) = "-"c)   If multiline Then     If response.Length > 3 Then       replyCode = response.Substring(0, 3)     End If     Dim line As String = ""     Dim lastLineReached As Boolean = False     While Not lastLineReached       receivedByteCount = controlSocket.Receive(bytes)       line = Encoding.ASCII.GetString(bytes, 0, receivedByteCount)       response += line       If line.IndexOf(ControlChars.CrLf & replyCode & " ") <> -1 Then         lastLineReached = True       End If       If lastLineReached Then         'just wait until CRLF is reached         While Not line.EndsWith(ControlChars.CrLf)           receivedByteCount = controlSocket.Receive(bytes)           line = Encoding.ASCII.GetString(bytes, 0, receivedByteCount)           response += line         End While       End If     End While   Else     While receivedByteCount = bytes.Length And _       Not response.EndsWith(ControlChars.CrLf)       receivedByteCount = controlSocket.Receive(bytes)       response += Encoding.ASCII.GetString(bytes, 0, receivedByteCount)     End While   End If   Console.WriteLine()   Console.Write(response)   If response.Length > 3 Then     replyCode = response.Substring(0, 3)     replyMessage = response.Substring(3, response.Length - 3)   Else     replyCode = ""     replyMessage = "Unexpected Error has occurred."   End If End Sub 
end example

The first thing this method does is to check the fourth byte of the reply to determine whether the server reply is a single-line or a multiline response. The fourth byte in a single-line response is a space, whereas it will be a hyphen in a multiline response:

 Dim bytes(511) As Byte ' an array of 512 bytes Dim receivedByteCount As Integer Dim response As String = "" ' get the first line receivedByteCount = controlSocket.Receive(bytes) response = Encoding.ASCII.GetString(bytes, 0, receivedByteCount) Dim multiline As Boolean = (response.Chars(3) = "-"c) 

If the response is multilined, the GetResponse method reads the reply code (the first three digits of the first line) and keeps reading the response in a While loop until the last line is reached. The last line is a line that starts with a reply code:

 If multiline Then   If response.Length > 3 Then     replyCode = response.Substring(0, 3)   End If   Dim line As String = ""   Dim lastLineReached As Boolean = False   While Not lastLineReached     receivedByteCount = controlSocket.Receive(bytes)     line = Encoding.ASCII.GetString(bytes, 0, receivedByteCount)     response += line     If line.IndexOf(ControlChars.CrLf & replyCode & " ") <> -1 Then       lastLineReached = True     End If 

When the last line is reached, it continues reading until the last byte is received:

 If lastLineReached Then   'just wait until CRLF is reached   While Not line.EndsWith(ControlChars.CrLf)     receivedByteCount = controlSocket.Receive(bytes)     line = Encoding.ASCII.GetString(bytes, 0, receivedByteCount)     response += line   End While 

If it is a single-line response, it just continues reading until the last byte in the stream is received:

 Else   While receivedByteCount = bytes.Length And _     Not response.EndsWith(ControlChars.CrLf)     receivedByteCount = controlSocket.Receive(bytes)     response += Encoding.ASCII.GetString(bytes, 0, receivedByteCount)   End While 

The response will then be sent to the console:

 Console.WriteLine() Console.Write(response) 

Next, replyCode and replyMessage are assigned the reply code and message of the server response, respectively:

 replyCode = response.Substring(0, 3) replyMessage = response.Substring(3, response.Length - 3) 

Login

The Login method accepts a username and a password that will be sent as the user's credential to log in to the connected FTP server (see Listing 5-4).

Listing 5-4: The Login Method

start example
 Public Function Login(ByVal userName As String, ByVal password As String) As String   If controlSocket.Connected Then     ' Sending user name     Dim command As String     command = "USER " & userName & ControlChars.CrLf     Console.WriteLine(command)     SendCommand(command)     GetResponse()     ' Sending password     command = "PASS " & password & ControlChars.CrLf     Console.Write("PASS") 'do not display password     SendCommand(command)     GetResponse()     Return replyCode   Else     Console.Write("Login failed because no connection is available")   End If   Return "" End Function 
end example

The Login method sends the USER and PASS commands in sequence. It returns the three-digit reply code. Login is successful only if the three-digit code is 230.

SendCommand

The SendCommand method sends a command to the connected FTP server (see Listing 5-5).

Listing 5-5: The SendCommand Method

start example
 Private Sub SendCommand(ByVal command As String)   Try     controlSocket.Send(Encoding.ASCII.GetBytes(command), command.Length, 0)   Catch   End Try End Sub 
end example

SendCWDCommand

The SendCWDCommand method uses the SendCommand method to send a CWD command to the connected FTP server (see Listing 5-6).

Listing 5-6: The SendCWDCommand Method

start example
 Public Sub SendCWDCommand(ByVal path As String)   SendCommand("CWD " & path & ControlChars.CrLf)   GetResponse() End Sub 
end example

SendDELECommand

The SendDELECommand method sends a DELE command to the connected FTP server using the SendCommand method (see Listing 5-7).

Listing 5-7: The SendDELECommand Method

start example
 Public Sub SendDELECommand(ByVal filename As String)   SendCommand("DELE " & filename & ControlChars.CrLf)   GetResponse() End Sub 
end example

SendLISTCommand

The SendLISTCommand method sends a LIST command to the connected FTP server and displays the returned directory list (see Listing 5-8).

Listing 5-8: The SendLISTCommand Method

start example
 Public Sub SendLISTCommand()   PassiveDataConnection()   SendCommand("LIST" & ControlChars.CrLf)   GetResponse()   Dim byteReceivedCount As Integer   Dim msg As New StringBuilder(2048)   Dim bytes(511) As Byte   Do     byteReceivedCount = _       dataSocket.Receive(bytes, bytes.Length, SocketFlags.None)     msg.Append(Encoding.ASCII.GetString(bytes, 0, byteReceivedCount))   Loop Until byteReceivedCount = 0   Console.WriteLine(msg.ToString())   'because the 226 response might be sent   'before the data connection finishes, only try to get "completion message"   'if it's not yet sent   If replyMessage.IndexOf("226 ") = -1 Then     GetResponse()   End If End Sub 
end example

The SendLISTCommand method starts by calling the PassiveDataConnection and sends the LIST command:

 PassiveDataConnection() SendCommand("LIST" & ControlChars.CrLf)     GetResponse() 

The data socket instantiated in the PassiveDataConnection method then reads the data from the server:

 Dim byteReceivedCount As Integer Dim msg As New StringBuilder(2048) Dim bytes(511) As Byte Do   byteReceivedCount = _     dataSocket.Receive(bytes, bytes.Length, SocketFlags.None)   msg.Append(Encoding.ASCII.GetString(bytes, 0, byteReceivedCount)) Loop Until byteReceivedCount = 0 

The data then displays on the console:

 Console.WriteLine(msg.ToString()) 

Upon sending the directory list, the server should send the 226 reply code indicating the transfer completion. However, in my testing, the 226 reply code might be sent before the data is received. Therefore, you call the GetResponse method only if the 226 reply code has not been sent:

 If replyMessage.IndexOf("226 ") = -1 Then   GetResponse() End If 

SendMKDCommand

The SendMKCommand method sends an MKD command to the connected FTP server (see Listing 5-9).

Listing 5-9: The SendMKDCommand Method

start example
 Public Sub SendMKDCommand(ByVal dir As String)   SendCommand("MKD " & dir & ControlChars.CrLf)   GetResponse() End Sub 
end example

SendPWDCommand

The SendPWDCommand method sends a PWD command to the connected FTP server (see Listing 5-10).

Listing 5-10: The SendPWDCommand Method

start example
 Public Sub SendPWDCommand()   SendCommand("PWD" & ControlChars.CrLf)   GetResponse() End Sub 
end example

SendRMDCommand

The SendRMDCommand method sends a RMD command to the connected FTP server (see Listing 5-11).

Listing 5-11: The SendRMDCommand Method

start example
 Public Sub SendRMDCommand(ByVal dir As String)   SendCommand("RMD " & dir & ControlChars.CrLf)   GetResponse() End Sub 
end example

SendQUITCommand

The SendQUITCommand method sends a QUIT command to the connected FTP server (see Listing 5-12). After the response is received, it calls the Shutdown and Close methods of the control socket.

Listing 5-12: The SendQUITCommand Method

start example
 Public Sub SendQUITCommand()   SendCommand("QUIT" & ControlChars.CrLf)   GetResponse()   controlSocket.Shutdown(SocketShutdown.Both)   controlSocket.Close() End Sub 
end example

SendRETRCommand

The SendRETRCommand method downloads a file in the connected FTP server (see Listing 5-13).

Listing 5-13: The SendRETRCommand Method

start example
 Public Sub SendRETRCommand(ByVal filename As String)   Dim f As FileStream = File.Create(filename)   SendTYPECommand("I")   PassiveDataConnection()   SendCommand("RETR " & filename & ControlChars.CrLf)   GetResponse()   Dim byteReceivedCount As Integer   Dim totalByteReceived As Integer = 0   Dim bytes(511) As Byte   Do     byteReceivedCount = _       dataSocket.Receive(bytes, bytes.Length, SocketFlags.None)     totalByteReceived += byteReceivedCount     f.Write(bytes, 0, byteReceivedCount)   Loop Until byteReceivedCount = 0   f.Close()   'because the 226 response might be sent   'before the data connection finishes, only try to get "completion message"   'if it's not yet sent   If replyMessage.IndexOf("226 ") = -1 Then     GetResponse()   End If   SendTYPECommand("A") End Sub 
end example

The method starts by creating a file in the current local directory:

 Dim f As FileStream = File.Create(filename) 

It then changes the transmission mode to image (binary) by calling the Send-TYPECommand method, passing "I" to the method:

 SendTYPECommand("I") 

Next, it calls the PassiveDataConnection method to get a data socket for the data transmission and sends a RETR command to the server:

 PassiveDataConnection() SendCommand("RETR " & filename & ControlChars.CrLf) GetResponse() 

The data socket created in the PassiveDataConnection method is then used to read the data stream. The incoming stream is written to the file created at the beginning of this method:

 Dim byteReceivedCount As Integer Dim totalByteReceived As Integer = 0 Dim bytes(511) As Byte Do   byteReceivedCount = _     dataSocket.Receive(bytes, bytes.Length, SocketFlags.None)   totalByteReceived += byteReceivedCount   f.Write(bytes, 0, byteReceivedCount) Loop Until byteReceivedCount = 0 

Next, the file closes:

 f.Close() 

After the data transmission completes, the server closes the data connection and sends a 226 transfer completion code through the control connection. However, the 226 reply code might be sent before all the data is received. Therefore, you call the GetResponse method only if the 226 reply code has not been sent:

 If replyMessage.IndexOf("226 ") = -1 Then   GetResponse() End If 

Finally, it changes the mode back to ASCII:

 SendTYPECommand("A") 

SendSTORCommand

The SendSTORCommand method uploads a file in the connected FTP server (see Listing 5-14).

Listing 5-14: The SendSTORCommand Method

start example
 Public Sub SendSTORCommand(ByVal filename As String)   Dim f As FileStream = File.Open(filename, FileMode.Open)   SendTYPECommand("I")   PassiveDataConnection()   SendCommand("STOR " & filename & ControlChars.CrLf)   GetResponse()   Dim byteReadCount As Integer   Dim totalByteSent As Integer   Dim bytes(511) As Byte   Do     byteReadCount = f.Read(bytes, 0, bytes.Length)     If byteReadCount <> 0 Then       dataSocket.Send(bytes, byteReadCount, SocketFlags.None)       totalByteSent += byteReadCount     End If   Loop Until byteReadCount = 0   dataSocket.Shutdown(SocketShutdown.Both)   dataSocket.Close()   f.Close()   GetResponse()   SendTYPECommand("A") End Sub 
end example

The method starts by opening the file to upload to the connected FTP server:

 Dim f As FileStream = File.Open(filename, FileMode.Open) 

It then changes the transmission mode to image (binary) and calls the PassiveDataConnection to obtain a data socket for the file transmission:

 SendTYPECommand("I") PassiveDataConnection() 

Then it sends a STOR command to indicate to the server that it is going to send a file to that server:

 SendCommand("STOR " & filename & ControlChars.CrLf) GetResponse() 

The data socket created by the PassiveDataConnection transfers the file.

 Dim byteReadCount As Integer Dim totalByteSent As Integer Dim bytes(511) As Byte Do   byteReadCount = f.Read(bytes, 0, bytes.Length)   If byteReadCount <> 0 Then     dataSocket.Send(bytes, byteReadCount, SocketFlags.None)     totalByteSent += byteReadCount   End If Loop Until byteReadCount = 0 

After the file transfer completes, the data socket closes:

 dataSocket.Shutdown(SocketShutdown.Both) dataSocket.Close() 

Then, the file closes and the mode switches back to ASCII:

 f.Close() GetResponse() SendTYPECommand("A") 

SendSYSTCommand

The SendSYSTCommand method sends a SYST method to the connected FTP server (see Listing 5-15).

Listing 5-15: The SendSYSTCommand Method

start example
 Public Sub SendSYSTCommand()   SendCommand("SYST" & ControlChars.CrLf)   GetResponse() End Sub 
end example

SendTYPECommand

You use the SendTYPECommand method to change the transmission mode from the client to the server (see Listing 5-16).

Listing 5-16: The SendTYPECommand Method

start example
 Public Sub SendTYPECommand(ByVal type As String)   SendCommand("TYPE " & type & ControlChars.CrLf)   GetResponse() End Sub 
end example

Main

The Main static method is the entry point of the program. It does the following:

  • Ensures that the program is invoked using the correct number of arguments.

  • Controls the program flow with a While loop so that the user can enter one FTP command after the execution of another.

  • Invokes the correct method upon receiving a valid user input.

  • Displays an error message on receiving an invalid user input.

Listing 5-17 shows the Main method.

Listing 5-17: The Main Method

start example
 Public Shared Sub Main(ByVal args As String())   If args.Length <> 3 Then     Console.WriteLine("usage: NETFTP server username password")   Else     Dim ftp As New NETFTP()     ftp.Connect(args(0))     Dim replyCode As String = ftp.Login(args(1), args(2))     If replyCode.Equals("230") Then       'login successful, allow user to type in commands       ftp.SendSYSTCommand()       ftp.SendTYPECommand("A")       Dim command As String = ""       Try         While Not command.ToUpper.Equals("QUIT")           Console.Write("NETFTP>")           command = Console.ReadLine().Trim()           If command.ToUpper.Equals("PWD") Then             ftp.SendPWDCommand()           ElseIf command.ToUpper.StartsWith("CWD") Then             If command.Length > 3 Then               Dim path As String = command.Substring(4).Trim()               If path.Equals("") Then                 Console.WriteLine("Please specify the directory to change to")               Else                 ftp.SendCWDCommand(path)               End If             End If           ElseIf command.ToUpper.StartsWith("DELE") Then             If command.Length > 4 Then               Dim path As String = command.Substring(5).Trim()               If path.Equals("") Then                 Console.WriteLine("Please specify the file to delete")               Else                 ftp.SendDELECommand(path)               End If             End If           ElseIf command.ToUpper.Equals("LIST") Then             ftp.SendLISTCommand()           ElseIf command.ToUpper.StartsWith("MKD") Then             If command.Length > 3 Then               Dim dir As String = command.Substring(4).Trim()                 If dir.Equals("") Then                   Console.WriteLine("Please specify the name of the directory to create")               Else                 ftp.SendMKDCommand(dir)               End If             End If           ElseIf command.ToUpper.Equals("QUIT") Then           ElseIf command.ToUpper.StartsWith("RMD") Then             If command.Length > 3 Then               Dim dir As String = command.Substring(4).Trim()               If dir.Equals("") Then                 Console.WriteLine("Please specify the name of the directory to delete")               Else                 ftp.SendRMDCommand(dir)               End If             End If           ElseIf command.ToUpper.StartsWith("RETR") Then             If command.Length > 4 Then               Dim filename As String = command.Substring(5).Trim()               If filename.Equals("") Then                 Console.WriteLine("Please specify a file to retrieve")               Else                 ftp.SendRETRCommand(filename)               End If             End If           ElseIf command.ToUpper.StartsWith("STOR") Then             If command.Length > 4 Then               Dim filename As String = command.Substring(5).Trim()               If filename.Equals("") Then                 Console.WriteLine("Please specify a file to store")               Else                 ftp.SendSTORCommand(filename)               End If             End If           Else             Console.WriteLine("Invalid command.")           End If         End While         ftp.SendQUITCommand()       Catch e As Exception         Console.WriteLine(e.ToString())       End Try       Console.WriteLine("Thank you for using NETFTP.")     Else       ftp.SendQUITCommand()       Console.WriteLine("Login failed. Please try again.")     End If   End If End Sub 
end example

The Main method starts by checking that the user passes three arguments: server, username, and password. If the number of arguments is not three, it prints the following message on the console:

 usage: NETFTP server username password 

If the number of arguments is correct, the Main method instantiates a NETFTP object and uses the first argument (server) to connect to the remote server by calling the Connect method:

 ftp.Connect(args(0)) 

Once connected, the Main method uses the second and third argument to log in by calling the Login method:

 Dim replyCode As String = ftp.Login(args(1), args(2)) 

The remote server returning a reply code of 230 indicates a successful login. If login was successful, it calls the SendSYSTCommand and SendTYPECommand methods. The SendSYSTCommand method prints the server's operating system information, and the SendTYPECommand method is called by passing "A" as the argument. This in effect changes the transfer mode to ASCII:

 If replyCode.Equals("230") Then   'login successful, allow user to type in commands   ftp.SendSYSTCommand()   ftp.SendTYPECommand("A") 

After the user is successfully logged in, the program enters a While loop. Inside the While loop is the code that gets the user's input and sends the corresponding FTP command. Control exits the While loop when the user types QUIT:

 Dim command As String = "" Try   While Not command.ToUpper.Equals("QUIT") 

Inside the While loop, the Main method first displays the NETFTP> prompt and uses the Console class's ReadLine to read the user input:

 Console.Write("NETFTP>") command = Console.ReadLine().Trim() 

Then, it goes through a series of If commands to execute code based on the command entered by the user. Valid commands are PWD, CWD, DELE, LIST, MKD, QUIT, RMD, RETR, and STOR.

If the command equals PWD, the SendPWDCommand method is called:

 If command.ToUpper.Equals("PWD") Then ftp.SendPWDCommand() 

If the command is CWD, it ensures that there is a parameter, a path, after the CWD command and that the parameter does not consist of spaces only. If the path looks valid, it calls the SendCWDCommand method. Otherwise, it prints a warning on the console:

 ElseIf command.ToUpper.StartsWith("CWD") Then   If command.Length > 3 Then     Dim path As String = command.Substring(4).Trim()     If path.Equals("") Then       Console.WriteLine("Please specify the directory to change to")     Else       ftp.SendCWDCommand(path)     End If   End If 

If the command is DELE, it makes sure there is a valid parameter, a filename. If the command has a valid parameter, it invokes the SendDELECommand method. Otherwise, it prints a warning to the user:

 ElseIf command.ToUpper.StartsWith("DELE") Then   If command.Length > 4 Then     Dim path As String = command.Substring(5).Trim()     If path.Equals("") Then       Console.WriteLine("Please specify the file to delete")     Else       ftp.SendDELECommand(path)     End If   End If 

If the command equals LIST, it invokes the SendLISTCommand method:

 ElseIf command.ToUpper.Equals("LIST") Then   ftp.SendLISTCommand() 

If the command starts with MKD and there is a valid parameter (a directory name), it calls the SendMKDCommand method. Otherwise, a warning displays on the console:

 ElseIf command.ToUpper.StartsWith("MKD") Then   If command.Length > 3 Then     Dim dir As String = command.Substring(4).Trim()     If dir.Equals("") Then       Console.WriteLine("Please specify the name of the directory to create")     Else       ftp.SendMKDCommand(dir)     End If   End If 

If the command equals QUIT, it does not do anything as this will be captured by the conditional statement in the While loop:

 ElseIf command.ToUpper.Equals("QUIT") Then 

If the command starts with RMD and there is a valid parameter (a directory name to remove), it invokes the SendRMDCommand method. Otherwise, a warning displays on the console:

 ElseIf command.ToUpper.StartsWith("RMD") Then   If command.Length > 3 Then     Dim dir As String = command.Substring(4).Trim()     If dir.Equals("") Then       Console.WriteLine("Please specify the name of the directory to delete")     Else       ftp.SendRMDCommand(dir)     End If   End If 

If the command starts with RETR and there is a parameter (a filename), the SendRETRCommand method is invoked. Otherwise, it prints a warning on the console:

 ElseIf command.ToUpper.StartsWith("RETR") Then   If command.Length > 4 Then     Dim filename As String = command.Substring(5).Trim()     If filename.Equals("") Then       Console.WriteLine("Please specify a file to retrieve")     Else       ftp.SendRETRCommand(filename)     End If   End If 

If the command starts with STOR and there is a parameter (a filename), it invokes the SendSTORCommand method. Otherwise, it prints a warning on the console:

 ElseIf command.ToUpper.StartsWith("STOR") Then   If command.Length > 4 Then     Dim filename As String = command.Substring(5).Trim()     If filename.Equals("") Then       Console.WriteLine("Please specify a file to store")     Else       ftp.SendSTORCommand(filename)     End If   End If 

Finally, if the command is none of the valid commands, it simply prints "Invalid command" on the console:

 Else   Console.WriteLine("Invalid command.") End If 

When the user types QUIT, the control exits the While loop, and the SendQUITCommand method is invoked:

 ftp.SendQUITCommand() 

Before closing itself, the program prints a thank you message.

 Console.WriteLine("Thank you for using NETFTP.") 




Real World. NET Applications
Real-World .NET Applications
ISBN: 1590590821
EAN: 2147483647
Year: 2005
Pages: 82

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net