65.9K
CodeProject is changing. Read more.
Home

File Transfer Protocol (FTP) Client

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (20 votes)

Dec 1, 2011

CPOL

7 min read

viewsIcon

280286

downloadIcon

26727

Connect to FTP server, and download, upload, rename, and delete files or directories.

Introduction

I know there are a lot of FTP client programs available on the Internet. But we also need to understand FTP (File Transfer Protocol)'s substructure. So this Open Source project will lead your way when trying to learn about FTP. This program's interface look like FileZilla. FileZilla is so popular but it has some bugs. It all started when I tried to open my blog. I needed to connect to my server via FTP, send files, download files, etc. So I decided to write my own application to handle all of this. FileZilla is good enough but it's not mine.

Background

Let's see what we know. We know FTP is a standard TCP based network protocol used to transfer files from one host to another host. And it's a client-server architecture.

ftp-hosting5.gif

FTP programs were based on command-lines. We can still use "cmd.exe" to connect to FTP servers because FTP works with commands. For example, to send a file, we can use "stor" from the command line. In order to do all of these, the FTP server needs to be running and waiting for incoming requests. We can better understand FTP from Wikipedia: "The client computer is able to communicate with the server on port 21 and it's called the control connection. It remains open for the duration of the session, with a second connection, called the data connection either opened by the server from its port 20 to a negotiated client port (active mode) or opened by the client from an arbitrary port to a negotiated server port (passive mode) as required to transfer file data. The control connection is used for session administration (i.e., commands, identification, passwords) exchanged between the client and server using a Telnet-like protocol. For example, "RETR filename" would transfer the specified file from the server to the client. Due to this two-port structure, FTP is considered an out-of-band protocol, as opposed to an in-band protocol such as HTTP."

embosip_FTP_Active.gif

"The server responds on the control connection with three digit status codes in ASCII with an optional text message, for example "200" (or "200 OK.") means that the last command was successful. The numbers represent the code number and the optional text represents explanations (e.g., <OK>) or needed parameters (e.g., <Need account for storing file>)." So what do we need to do? It's so clear. Send command, receive "OK" command, send data, receive data, and that's all. But first we should prepare the server. FTP servers can be run in "active" or "passive" mode. Active mode is a server based connection and passive is a client based connection. Let's see more.

In active connections, clients send the IP and port to the server then the server will try to connect to the client. But it could be denied by the client because of firewalls. We all use antivirus software or Windows Firewalls, right? Now let's see passive mode.

In passive connections, the server sends its IP and port to the client with a "PASV" command then the client can try to connect the server with this IP. It's a very usable way to send files. When we try to send a file, we should use the "PASV" mode first. And as you know, most protocols like FTP, HTTP use ASCII characters when trying to get something because it's a global mode. Because it's global, we will use this mode. And you can get the FTP command list from this URL: http://en.wikipedia.org/wiki/File_Transfer_Protocol.

Using the code

Now we are ready to prepare our application. Let's code something useful :) First of all, we need an "Open File dialog" but integrated with our Form.

File Explorer component

We need a file explorer component to see our files to send to the FTP server with our application's interface. Open a new project of type "Windows Forms User Control Library".

Component.png

It'll look like this. Now we need a treeview. A few buttons. And a search feature.

TreeView.Nodes.Clear();
TreeNode nodeD = new TreeNode();
nodeD.Tag = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
nodeD.Text = "Desktop";
nodeD.ImageIndex = 10;
nodeD.SelectedImageIndex = 10;
TreeView.Nodes.Add(nodeD);

Like shown in this code, we should add the main nodes first, "My Documents", "My Computer", etc. Then get the sub directories.

string[] dirList;
dirList = Directory.GetDirectories(parentNode.Tag.ToString());
Array.Sort(dirList);
if (dirList.Length == parentNode.Nodes.Count)
    return;
for (int i = 0; i < dirList.Length; i++)
{
    node = new TreeNode();
    node.Tag = dirList[i]; 
    node.Text = dirList[i].Substring(dirList[i].LastIndexOf(@"\") + 1);
    node.ImageIndex = 1;
    parentNode.Nodes.Add(node);
}

You can get the complete code from the link above. We should track the click, down events implemented by the mouse.

Now we have a file explorer, and all the needed information about FTP and Visual Studio.

First of all, we need to connect to the server. What should we do?

FTPSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
AppendText(rchLog,"Status : Resolving IP Address\n",Color.Red);
remoteAddress = Dns.GetHostEntry(Server).AddressList[0];
AppendText(rchLog, "Status : IP Address Found ->" + remoteAddress.ToString() + "\n", Color.Red);
addrEndPoint = new IPEndPoint(remoteAddress, Port);
AppendText(rchLog,"Status : EndPoint Found ->" + addrEndPoint.ToString() + "\n", Color.Red);
FTPSocket.Connect(addrEndPoint);

Yes, we need an open socket so connect to our server. Now we can send our commands:

AppendText(rchLog, "Command : " + msg + "\n", Color.Blue);
Byte[] CommandBytes = Encoding.ASCII.GetBytes((msg + "\r\n").ToCharArray());
FTPSocket.Send(CommandBytes, CommandBytes.Length, 0);
//read Response
ReadResponse();

We send our command to the server and it will answer but in its own language. We need to understand it. The answer include a 3 digit code and an explanation.

private string SplitResponse()
{
    try
    {
        while (true)
        {
            Bytes = FTPSocket.Receive(Buffer, Buffer.Length, 0); //Number Of Bytes (Count)
            StatusMessage += Encoding.ASCII.GetString(Buffer, 0, Bytes); //Convert to String
            if (Bytes < Buffer.Length)  //End Of Response
                break;
        }
        string[] msg = StatusMessage.Split('\n');
        if (StatusMessage.Length > 2)
            StatusMessage = msg[msg.Length - 2];  //Remove Last \n
        else
            StatusMessage = msg[0];
        if (!StatusMessage.Substring(3, 1).Equals(" "))
            return SplitResponse();
        for (int i = 0; i < msg.Length - 1; i++)
            AppendText(rchLog, "Response : " + msg[i] + "\n", Color.Green);
        return StatusMessage;
    }
    catch(Exception ex)
    {
        AppendText(rchLog, "Status : ERROR. " +ex.Message+ "\n", Color.Red);
        FTPSocket.Close();
        return "";
    }
}

Yes, that's all .Now we can download, upload, rename, or delete everything :)

List of FTP commands

For easy reference I am including the command list from Wikipedia:

Command RFC Description
ABOR Abort an active file transfer
ACCT Account information
ADAT RFC 2228 Authentication/Security data
ALLO Allocate sufficient disk space to receive a file
APPE Append
AUTH RFC 2228 Authentication/Security mechanism
CCC RFC 2228 Clear command channel
CDUP RFC 959 Change to parent directory
CONF RFC 2228 Confidentiality protection command
CWD RFC 697 Change working directory
DELE Delete file
ENC RFC 2228 Privacy protected channel
EPRT RFC 2428 Specifies an extended address and port to which the server should connect
EPSV RFC 2428 Enter extended passive mode
FEAT RFC 2389 Get the feature list implemented by the server
HELP Help
LANG RFC 2640 Language negotiation
LIST Returns information of a file or directory if specified, else information of the current working directory is returned
LPRT RFC 1639 Specifies a long address and port to which the server should connect
LPSV RFC 1639 Enter long passive mode
MDTM RFC 3659 Returns the last-modified time of a specified file
MIC RFC 2228 Integrity protected command
MKD RFC 959 Make directory
MLSD RFC 3659 List the contents of a directory if a directory is named
MLST RFC 3659 Provide data about exactly the object named on its command line, and no others
MODE Set the transfer mode (Stream, Block, or Compressed)
NLST Return a list of file names in a specified directory
NOOP No operation (dummy packet; used mostly on keepalives)
OPTS RFC 2389 Select options for a feature
PASS Authentication password
PASV Enter passive mode
PBSZ RFC 2228 Protection buffer size
PORT Specifies an address and port to which the server should connect
PROT RFC 2228 Data channel protection level
PWD RFC 959 Print working directory. Returns the current directory of the host.
QUIT Disconnect
REIN Re-initialize the connection
REST RFC 3659 Restart transfer from the specified point
RETR Transfer a copy of the file
RMD RFC 959 Remove a directory
RNFR Rename from
RNTO Rename to
SITE Send site specific commands to remote server
SIZE RFC 3659 Return the size of a file
SMNT RFC 959 Mount file structure
STAT Return the current status
STOR Accept the data and store the data as a file at the server site
STOU RFC 959 Store file uniquely
STRU Set file transfer structure
SYST RFC 959 Return system type
TYPE Set the transfer mode (ASCII/Binary)
USER Authentication username
XCUP RFC 775 Change to the parent of the current working directory
XMKD RFC 775 Make a directory
XPWD RFC 775 Print the current working directory
XRCP RFC 743
XRMD RFC 775 Remove the directory
XRSQ RFC 743
XSEM RFC 737 Send, mail if cannot
XSEN RFC 737 Send to terminal

A short list of reply codes

  • 2xx - Success reply
  • 4xx or 5xx - Failure reply
  • 1xx or 3xx - Error or Incomplete reply

The second digit defines the kind of error:

  • x0z - Syntax - These replies refer to syntax errors.
  • x1z - Information - Replies to requests for information.
  • x2z - Connections - Replies referring to the control and data connections.
  • x3z - Authentication and accounting - Replies for the login process and accounting procedures.
  • x4z - Not defined.
  • x5z - File system - These replies relay status codes from the server file system.

By the way, the last FTP Technology is RCF 2428 since 1998. It's an unimportant information. Because it's about FTP's history. But we looked at the RCF 959 technology and it has been in use since 1985.