amone
amone

Reputation: 3862

Send file to ftp server using sockets in C

I am trying to upload a file to my ftp server using sockets. It connects to the server and can read the directories but doesn't upload the file. "STOR" command creates a file in the server with an empty content. Why I am getting "No data connection" response from server and my file is empty?

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
    argv[0]="2";
    argv[1]="ip";

    int sockfd = 0, n = 0;
    char recvBuff[1024];
    struct sockaddr_in serv_addr;
    char mesUser[100]="USER ftpuser\n";
    char mesPass[100]="PASS pass\n";
    char meStor[100]="STOR xx\n";
    char mesPasv[100]="PASV\n";
    char meAppe[100]="APPE xx\n";

    argc=2;

    if(argc != 2)
    {
        printf("\n Usage: %s <ip of server> \n",argv[0]);
        return 1;
    }

    memset(recvBuff, '0',sizeof(recvBuff));
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Error : Could not create socket \n");
        return 1;
    }

    memset(&serv_addr, '0', sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(21);

    if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
     {
     printf("\n inet_pton error occured\n");
     return 1;
     }


    //serv_addr.sin_addr.s_addr = inet_addr(argv[1]);

    if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("\n Error : Connect Failed \n");
        return 1;
    }

    if( send(sockfd , mesUser , strlen(mesUser) , 0) < 0)
    {
        perror("send failed");
        return 1;
    }

    if( send(sockfd , mesPass , strlen(mesPass) , 0) < 0)
    {
        perror("send failed");
        return 1;
    }

    char* fr_name = "pic.jpg";
    FILE *fr = fopen(fr_name, "r");
    if(fr == NULL){
        printf("File cannot be opened");
        return 0;
    }
    else{

        /*if( send(sockfd , mesPasv , strlen(mesPasv) , 0) < 0)
        {
            perror("send failed");
            return 1;
        }*/

        if( send(sockfd , meStor , strlen(meStor) , 0) < 0)
        {
            perror("send failed");
            return 1;
        }



        char buffer[100];
        fscanf(fr,"%s",buffer);
        write(sockfd,buffer,100);


        if( send(sockfd , meAppe , strlen(meAppe) , 0) < 0)
        {
            perror("send failed");
            return 1;
        }
        //close(sockfd);


    }

    /*if( send(sockfd , meStor , strlen(meStor) , 0) < 0)
    {
        perror("send failed");
        return 1;
    }
    */

    while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
    {
        recvBuff[n] = 0;
        if(fputs(recvBuff, stdout) == EOF)
        {
            printf("\n Error : Fputs error\n");
            return 0;
        }
    }

    if(n < 0)
    {
        printf("\n Read error \n");
        return 0;
    } 

    return 0;
}

Output:

 220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 6 of 50 allowed.
220-Local time is now 14:41. Server port: 21.
220 You will be disconnected after 15 minutes of inactivity.
331 User username OK. Password required
230 OK. Current restricted directory is /
425 No data connection
425 No data connection

Upvotes: 1

Views: 20969

Answers (2)

eGhoul
eGhoul

Reputation: 2590

i hope this will be useful to you :

int receiveFile(int socket, char text[]) {
FILE *fp;
int nsize,k, i, size=0, temp_size, mul = 1, numbytes, lala, recvd; 
int count_freq, repeat;
char ch,buf[20],file_buf[505], temp_buf[505];
saferead(socket, text,80);
if(text[0] == '/')  
    return 1;


nsize = strlen(text);
char name[nsize];
strncpy(name, text, nsize-1);
name[nsize-1] = '\0';   

if ((fp = fopen(name,"w")) == NULL) {
        perror(" Can't open file");
    return 1;
}

if ((numbytes=recv(socket, buf, 10, 0)) == -1) {
    perror("Cant receive size of the file....\n\n");
    return 1;
}

for( i=0; i<=9; i++ ){
    size =  size + ( buf[i]*mul );
    mul = mul * 10;
}


recvd = 0;
printf("Received File: %s\n", name);
repeat = size/MAXDATASIZE;

if ( repeat>50 )
    count_freq = repeat/50;

i=0;    
while( recvd < size ){

    if ((numbytes=recv(socket, temp_buf, MAXDATASIZE, 0)) == -1) {
        perror("Error receiving file from server....\n\n");
        return 1;
    }

    fwrite( temp_buf, sizeof(temp_buf[0]), numbytes, fp );
    recvd = recvd + numbytes;
}
fclose(fp);  

}

int sendFile(int socket, char text[]) {
FILE *fp;
int size =0, k, status, nsize = 0, temp_size, i, sent, numbytes, lala;
char buf[20], file_buf[505], temp_buf[505];
char ch;
struct stat info;

nsize = strlen(text);
char name[nsize];
lala = strlen(name);
strncpy(name, text, nsize-1);
name[nsize-1] = '\0';   
lala = strlen(name);

if((fp = fopen(name, "r")) == NULL) {
    perror("Can't open file");
    text[0] = '/';
    write(socket,text, 80);
    return 1;
}
write(socket,text, 80);    
printf("Sending File: %s\n",text);

status = stat( name,&info );

if( status == -1 ){
    printf(" fstat failed \n");
    return 1;
}
size = info.st_size;
temp_size = size;

for( i=0; i<=9; i++ )   {
    buf[i] =  size%10;
    size = size/10;
}

if (send(socket, buf, 10, 0) == -1){
    perror("Cant send file size...\n\n");
    return 1;
}


i = 0;
sent = 0;
while( sent <= temp_size ){
    ch = fgetc(fp);
    if( sent == temp_size ){
        if (i>0){
            if (( numbytes = send(socket, file_buf, i, 0)) == -1)
                perror("Error in sending file.....\n\n\n");
        }
            break;
    }

    file_buf[i++] = ch;

    if(i == MAX_BUFSIZE){                   
        if (( numbytes = send(socket, file_buf, MAX_BUFSIZE, 0)) == -1)
                perror("Error in sending file....\n\n\n");
            i = 0;
    }   
        sent++;
}

fclose(fp);

}

Upvotes: 0

brenns10
brenns10

Reputation: 3369

It looks like you have an incomplete understanding of the FTP protocol. FTP works on the idea of having 2 socket connections between the client and the server. The first is a "control" connection, and the second is a "data" connection. On the control connection, text commands are sent back and forth, as you are doing in your code. When data needs to be sent back and forth, it is done using the data connection.

There are two ways for FTP to set up a data connection, described here:

  • Active: Client specifies a port to the server, and the server connects to that port on the client's machine. This is bad because firewalls and NAT are designed to avoid exactly these sorts of connections.
  • Passive: The server gives the client a port to connect to, and the client connects to that port on the server machine.

In brief, you'll need to:

  1. Use the PASV command.
  2. Parse the response from the server to get the port number (probably using scanf).
  3. Open a data connection to that port on the server.
  4. Put your file through that data connection.

It's been a while since I last wrote with sockets in C, and I don't have the time to write an example, but this should be enough to get you started. (Here is the specification for FTP. RFC's like this are heavy reading, but they are unambiguous and can answer a lot of questions, if you can learn to read them.)

Upvotes: 11

Related Questions