News


Just like with the previous entry on C# and telnet, creating an FTP session using C# is not as scary as it sounds. And even if you have to connect to a server that only understands RAW commands, that's not too bad either. Here's how:

Create a socket on port 21:

    //resolve IP address from DNS
    IPHostEntry dns = Dns.GetHostEntry(serverName);
    //create an endpoint to the server on port 21 (ftp default)
    IPEndPoint serverIP = new IPEndPoint(dns.AddressList[0], 21);
    //create a socket to that endpoint
    Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    //connect using the socket
    sock.Connect(serverIP);

If you want to, you can set some other properties of the socket:

    sock.SendTimeout = 2000; //2 seconds to send
    sock.ReceiveTimeout = 10000; //10 seconds to receive

Sending a message (string) and receiving a response through the socket goes like this (I chose to use the Thread.Sleep call because my server couldn't finish responding to my request in time for me to read the response immediately):

    //placeholder for response
    string resp = string.Empty;
    //placeholder for data to be received
    Byte[] bytesReceived = new Byte[1024];
    //track bytes
    int bytes = 0;
    //encode message into clear text
    Byte[] bytesSent = Encoding.ASCII.GetBytes(request);
    //send message
    sock.Send(bytesSent, bytesSent.Length, 0);
    //wait a while
    Thread.Sleep(1000);
    //listen for a response
    bytes = sock.Receive(bytesReceived, bytesReceived.Length, 0);
    //decode the response
    resp = Encoding.ASCII.GetString(bytesReceived, 0, bytes);

Next, here are the strings that I stored in the object "request". Order matters- mostly. And the "\n" parts are the carriage returns to tell the server to process the command. They may not be necessary in your case, they were in mine:

  1. "USER [username]\n"
  2. "PASS [password]\n"
  3. "CWD [path of the folder containing the file I want]\n"
  4. "TYPE I\n"
  5. "PASV\n"
  6. "RETR [file name]\n"

Explanation:
Steps 1 and 2: Simply transmitting credentials. The user name must be a user LOCAL TO THE SERVER, which may or may not be a network or domain account.
Step 3: Change the current directory to the folder containing the file you're going to download.
Step 4: Type I means we're dealing with binary- I want the file, not just the text inside the file. There are also Type A and probably some others. Search if you need them.
Step 5: PASV tells the server to get ready to send or receive. The server opens a port and gets ready for a connection. It then sends a response that looks like this: 227 Entering Passive Mode (127,0,0,1,172,209). The first four numbers (separated by commas) are the IP address of the server: 127.0.0.1, in this case. Then you take the 5th element in the list, multiply it by 256 and then add the 6th element to find the port number.
Between steps 5 and 6, you'll need to create a second socket to the server, this time on the port that you just calculated from the response.
Step 6: Send RETR to the first socket. As soon as you do, the second socket will begin to receive data from the server.

Finally, here's how to receive the file from the ftp server via the second socket.

    byte[] buffer = new byte[25000];
    int bytes = 0; //number of bytes received finally
    bytes = sock2.Receive(buffer);

There is a property of the socket called "Available" and it'll tell you how many bytes are ready to be read from the socket. But from moment to moment that should change as more data is transmitted across the wire. Basically, you can keep checking it until the number stops changing or you can wait a pre-specified amount of time and start receiving from the socket whether it's done or not.


posted @ Monday, November 05, 2007 3:12 PM |

Comments

Gravatar # re: C# (heart) RAW FTP
Posted by afgar on 5/23/2008 11:13 AM
Doesn't work
Gravatar # re: C# (heart) RAW FTP
Posted by Robert Bailey on 5/23/2008 11:51 AM
@afgar: Can you be more specific? It worked for me- otherwise I wouldn't have posted it.
Gravatar # re: C# (heart) RAW FTP
Posted by George A on 8/30/2008 5:08 PM
Connecting to the server is not a problem, neither sending RAW commands. The problem I get is when trying to open a 2nd socket connection after entering Passive Mode. The application waits for something but eventualy looses the connection because the remote location closed it.

Between steps 5 and 6 I create a new socket like above and tried to connect using the IPEndpoint(<Original IP address>,<new Port>.

I'm fairly new in c# especialy with socket etc.

Can you show me some code please?
Thanks.
Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: