Click to See Complete Forum and Search --> : FTP Client Help


bloodhound42
June 17th, 2004, 04:43 AM
Hi!

I'm having a problem creating my custom FTP
client. The problem is I can't get the remote
directory listing in my buffer.

I always get an error 426 Data connection close
and no data in my buffer.

Try reading some source codes, it just gets worse..

Does anybody know the detailed steps?

Here's the flowchart of my program;

1. create a socket
2. set the socket asynchronous mode.
3. do a connect() on the server on PORT 21
4. server replies +OK in my buffer.
5. send() a "USER username" command to server.
6. server replies +OK in my buffer. need password.
7. send() a "PASS password" command to server.
6. server replies +OK in my buffer. already login.
8. do a getsockname() on the server on PORT 21?
(i saw this on google forums, so far, i didn't understand
completely what to do with this)
9. send() a "LIST" command to server.
10. I get a reply Opening ASCII connection in my buffer.
11. then the Error 426.

Should I create two sockets? one for the data buffer
and one for the control/command that I already created?
I also just saw this on google forums. If yes, where/when
will I create the second socket and on what port? and do
I have to bind() it?

I just need the step by step procedure.

appreciate any help, thanks.
:wave:

Andreas Masur
June 17th, 2004, 07:24 AM
[Moved thread]

j0nas
June 17th, 2004, 07:23 PM
Some FTP requests require a data connection socket. All requests go through the control connection (default port 21), but some requests need a data connection. In your case, the LIST request requires a data connection, so the FTP server can send the actual file directory listing to the client-end. The data connection can be either active (default) or passive. An active data connection means that the FTP server connects to the FTP client. A passive data connection means the FTP client connects to the FTP server.

Before you send the LIST requst, you must setup a data connection socket (connect() for passive mode, and bind(), listen(), accept() for active mode). For active mode, you should send a PORT request before sending the LIST request. The PORT request specifies IP-ADDR and TCP-PORT for the FTP server to connect to. Again, details are found in the FTP RFC (RFC-959).

Attached ZIP file contains a PDF file that shows a FTP session (USER, PASS and LIST) that I captured with Ethereal (http://ftp.sunet.se/pub/network/monitoring/ethereal/win32/). As you can see, the data connection is active (the PORT request). (FTP client on 192.168.0.102 and FTP server on 192.168.0.10).

Hope it helps,
Jonas

Mathew Joy
June 18th, 2004, 12:27 AM
Kindly avoid reposting the same question.

bloodhound42
June 18th, 2004, 04:58 AM
Thanks j0nas!

I'm still trying your steps above and I'll let
you know when I get it right. The links you
gave me were a big help too.

I have some questions regarding the bind() part..

Do I use the bind() with the parameter FDREAD?
FDACCEPT? FDCONNECT? or FDLISTEN?

will I be using the address/port that I will be giving
in the PORT command on the bind() parameters?

So here are the steps, the way I understand your
above procedure (I'm using ACTIVE mode):

ACTIVE MODE:

1. Create another socket in asynchronous mode for data.
2. bind() (FD parameters?)
3. listen() details...
4. accept() details...
5. send() "PORT h1,h2,h3,h4,p1,p2"
where h1-h4 is the client address? and p1*256+p2
is the port you want the server to connect to?
6. recvfrom() the reply "PORT command successful"
7. send() "LIST" to port 21 on server's address
8. recvfrom() on port I use on the PORT command
the DIRECTORY LISTING???

please correct me if I'm wrong..

Thanks, you're a very big help!:wave:

j0nas
June 18th, 2004, 05:57 AM
I don't know what you mean with bind() and FD parameters... I think you have mixed it up with select().

Try the easiest frist, I mean by using blocking sockets. Try something like this:

1. cs = socket(...) // control connection socket
2. connect(cs, ...)
3. send(cs, "USER <user>")
3b) Parse response (recv(cs,...) etc)
4. send(cs, "PASS <pass>")
4b) Parse response
5. Create data connection: ls = socket(...)
6. bind(ls,...), set addr to INADDR_ANY, and port to 0
7. listen(ls,..)
8. Call getsockname(ls, ...) to findout which IP and port number bind() created in step 6 (this is needed for the PORT request)
9. send(cs, "PORT <IP and port from getsockname>")
9b) Parse response
10. send(cs, "LIST")
10b) Prase response
11. dcs = accept(ls, ...) // creates the data connection socket when FTP server connects to it
12. Do recv(dcs, ...) while it returns > 0
13. closesocket(dcs) and parse the response from the LIST request
14. closesocket(ls)

Hmm... I think I got everything right.. Try it.

bloodhound42
June 20th, 2004, 02:09 AM
Thanks again j0nas! :)

I'll try your step by step procedure above and
will PM you or post a reply here ASAP.

Now that is one CLEAR procedure! :thumb::thumb::thumb::thumb::thumb:

BIG thanks to you! :wave:

P.S.: I assume that I'll also be using this same
procedure when I do (GET/PUT) file transfers, right? ;)