|
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:
- "USER [username]\n"
- "PASS [password]\n"
- "CWD [path of the folder containing the file I want]\n"
- "TYPE I\n"
- "PASV\n"
- "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.
|