I have a task "Send file to distant FTP server". I have written code, but it's not working correctly. I create a socket for data transferring and try to upload my file. After uploading the file, I want to check the server answer using recv()
, but my program hangs at this moment, but I can see my file on server. If I remove recv()
from my code, the size of my file is 0 bytes. I have been trying to solve this problem for a couple of days. Can anyone help me?
I'm using this FTP server for testing: ftp://speedtest.tele2.net/
int upload_file(char *filename) {
char str[256];
char buff[1024];
int getFile;
int bytes_read;
//ds - for data
sprintf(str, "CWD %s\r\n", "upload");
send(s, str, strlen(str), 0);
get_server_answer();
switch_to_passive_mode();
sprintf(str, "TYPE I\r\n");
send(s, str, strlen(str), 0);
get_server_answer();
sprintf(str, "STOR %s\r\n", filename);
send(s, str, strlen(str), 0);
get_server_answer();
getFile = open(filename, O_RDONLY, 0644);
while (1) {
bytes_read = read(getFile, buff, 1024);
if (bytes_read <= 0)
break;
send(ds, buff, bytes_read, 0);
}
char tmp[256];
recv(s, tmp, 256, MSG_WAITALL); // program hangs here
close(getFile);
close(ds);
close(s);
return 0;
}
By default, FTP data transfers operate in STREAM
transmission mode. In that mode, after sending the file data over your ds
socket, you need to close the ds
socket to signal End-Of-File to the server, before attempting to read the server's answer (why are you not using get_server_answer()
instead?). Since you are not doing that, you are waiting for a final server answer that is never being sent.
When you remove the recv()
, you are closing both the ds
and s
sockets. By closing the s
socket without sending a QUIT
command first, the server thinks your client has vanished unexpectedly before receiving the server's answer, and so it aborts the transfer.
So, you need to either:
close ds
(but not s
!) after your loop is finished, but before you read the answer.
use the MODE
command to switch the data connection's transmission mode to BLOCK
or COMPRESSED
mode, which don't signal EOF by closing the data connection. See RFC 959 Section 3.4 for more details.
Also, you are not validating that the initial answer to the STOR
command is successful (has a reply code of 125 or 150) before sending the file data over ds