csocketsftpnetwork-programmingrecv

Sending file to distant FTP server


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;
}

Solution

  • 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:

    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