> Thanks..could you please clarify, what does "open" mean in this
> case? I thought I was doing that if means connecting and logging in
> to the ftp server first.
FTP uses a control connection to send commands from client to server
and to receive status and other information from the server. A single
control connection is made from client to server, and it remains open
for the duration of the session.
But files are transferred using a separate data connection for each
transfer.
You have already opened the control connection, but the PASV command
determines how the *data* connection(s) will be made. In PASV mode,
the server opens a second ServerSocket, then responds with its address
and port number for the client to connect to. In active mode, the
client opens a ServerSocket, then sends its address and port number
for the server to connect to.
getPassiveHost()/getPassivePort() are used after establishing a data
connection. In your example, you have attempted to use them after
establishing the control connection, but before establishing any data
connection, so you get null/-1.
/gordon

Signature
[ don't email me support questions or followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
Christopher Smith - 07 Sep 2006 03:49 GMT
Gordon Beaton <n.o.t@for.email> wrote in news:44fd5fe5$0$17139$8404b019
@news.wineasy.se:
> You have already opened the control connection, but the PASV command
> determines how the *data* connection(s) will be made. In PASV mode,
> the server opens a second ServerSocket, then responds with its address
> and port number for the client to connect to. In active mode, the
> client opens a ServerSocket, then sends its address and port number
> for the server to connect to.
This makes it much clearer...thanks. So got ethereal, and am looking at
the packets.
Okay, very weird.
It appears that:
1. the connection goes fine on port 21.
2. the passive request is issued to the ftp server.
3. the ftp server responds with the correct address and port data I setup
in the config file (vsftpd)...the ports I told it to use ranged from
1200-1203.
4. Then the client sends a message (SYN FLAG SET) to the server on the
correct port for the passive transfer (i.e., the open connection makes it
through the firewall).
5. the server responds with an acknolwedge from the source port opened
by the client (1203).
6. The request to transfer the file comes from the client on port 21,
the control port.
7. THEN THE WEIRD PART. data starts flowing from the server to the
client. I can actually see the data through the sniffer...it is correct.
8. The client even responds with acknowledge ment.
9. Mysteriously, the client then requests to quit.
What's happening? Is this a situaiton where I need to issue the
completePendingCommand() method or something like that?
Gordon Beaton - 07 Sep 2006 07:27 GMT
> What's happening? Is this a situaiton where I need to issue the
> completePendingCommand() method or something like that?
That's great that you got Ethereal to look at the traffic. It really
helps to understand what is actually happening.
Here you get the InputStream and create an InputStreamReader, but
don't actually read from it:
isr = new InputStreamReader (ftp.retrieveFileStream("xxxx.csv"));
Once the data connection is active the server is able to start sending
data, which gets buffered (to a point) at the client until you start
reading it. But then you do this:
boolean success = ftp.completePendingCommand();
...which (I'm not sure here) interrupts the command. What does
"success" contain after this? I'm not convinced this method is
necessary here, but then I've never used this library for ftp.
Two important things here:
1. in most cases, you should read directly from the InputStream
returned by retrieveFileStream(), without using an
InputStreamReader. A *possible* exception to this rule is when you
know the data is text. However even then you should specify the
correct character encoding when you create the InputStreamReader.
2. you need to actually *read* the data arriving from the server. Read
until you get EOF (InputStream.read() returns -1), then close the
InputStream.
/gordon

Signature
[ don't email me support questions or followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
Gordon Beaton - 07 Sep 2006 07:34 GMT
> 1. in most cases, you should read directly from the InputStream
> returned by retrieveFileStream(), without using an
> InputStreamReader. A *possible* exception to this rule is when you
> know the data is text. However even then you should specify the
> correct character encoding when you create the InputStreamReader.
...and if you aren't expecting text, you should always use
setFileType(FTP.IMAGE_FILE_TYPE), otherwise the data may be corrupted
by the transfer.
/gordon

Signature
[ don't email me support questions or followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e