Geeks With Blogs
They call me Big Papa 4 kids and counting

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 on Monday, November 5, 2007 3:12 PM | Back to top


Comments on this post: C# (heart) RAW FTP

# re: C# (heart) RAW FTP
Requesting Gravatar...
Doesn't work
Left by afgar on May 23, 2008 11:13 AM

# re: C# (heart) RAW FTP
Requesting Gravatar...
@afgar: Can you be more specific? It worked for me- otherwise I wouldn't have posted it.
Left by Robert Bailey on May 23, 2008 11:51 AM

# re: C# (heart) RAW FTP
Requesting Gravatar...
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.
Left by George A on Aug 30, 2008 5:08 PM

# re: C# (heart) RAW FTP
Requesting Gravatar...
hi, ... I have the same problem... Im implementing a simple ftp server in C# and I see it from the server side... I receive the PASV, Issue the 257 response, open another listener on the endpoint specified in 257, try to send the 257 response, but the client is already disconnected... hmm
Left by michal on Mar 26, 2010 10:12 AM

# re: C# (heart) RAW FTP
Requesting Gravatar...
I have a working FTP Class that I created that uses Passive Mode for data transferring. Do you happen to know how to create an Active Mode fallback when the client is unable to connect using passive? =P You'd be my favorite person in the world.
Left by John Strickler on Aug 04, 2010 3:57 PM

# re: C# (heart) RAW FTP
Requesting Gravatar...
I need some help with this code. I don't understand how to declare the variable "request". Please this is urgent. Thanks
Left by Diego Gualotuña on Nov 14, 2010 3:16 PM

# re: C# (heart) RAW FTP
Requesting Gravatar...
This was *incredibly* helpful in creating an alternate solution to the .NET FtpWebRequest/FtpWebResponse objects and their no-CWD-command bs.

Thanks.
Left by Jesse on Aug 18, 2011 11:08 AM

Your comment:
 (will show your gravatar)
 


Copyright © baileyrt | Powered by: GeeksWithBlogs.net | Join free