Thread: multiple forks in one client connection (ftpclient)

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    10

    multiple forks in one client connection (ftpclient)

    Hi,
    I am new to socket programming, I wrote an ftpclient which connects to an ftp server and downloads a file to the client computer.
    Now in one client connection I want to download multiple files by forking the parent connection.
    So far I have this, the code downloads only one file, and then gives the following error
    "Transfer Completed425 Unable to build data connection: Invalid argument"
    There is something basic that I am missing or taking an altogether wrong approach?
    Appreciate if someone can help me here.
    Code:
    /*******************************************************************************
    Object:		This is a ftp client which communicates with a ftp server
    		on port 21 (ftp-data port 20 RFC 959)
    Input:		IPAddress to connect to / username & password to connect to ftp server
    		filename to be downloaded (with path if not in the ftp directory of the user)
    Functioning:	Creates a ftp socket
    		A connection is established with the ftp server at the ip addr. and port 21 
    		After the connection is established user authentication is done with server 
    		and response is received.
    		Once the user is authenticated a request to download the specified file is sent to the ftp server
    Output:		None (though specified file is downloaded to the client machine).
    
    ********************************************************************************/
    #include <stdio.h>        /* for printf() and fprintf() */
    #include <sys/socket.h>   /* for socket(), connect(), send(), and recv() */
    #include <arpa/inet.h>    /* for sockaddr_in and inet_addr() */
    #include <stdlib.h>       /* for atoi() */
    #include <string.h>       /* for memset() */
    #include <unistd.h>       /* for close() */
    #include <netdb.h>
    #include <errno.h>
    #include <sys/wait.h>
    #include <signal.h>
    #define RCVBUFSIZE 32     /* Size of receive buffer */
    
    void DieWithError(char *errorMessage);    /* Error handling function */
    int ftpSendFile(char * buf, char * host, int port);
    int ftpRecvResponse(int sock, char * buf);
    int ftpNewCmd(int Sock, char * buf, char * cmd, char * param);
    int ftpConvertAddr(char * buf, char * hostname, int * port);
    
    /************************************
    for collecting zoombie processes
    *************************************/
    
    void sigchld_handler(int s)
    {
        while(waitpid(-1, NULL, WNOHANG) > 0);
    }
    
    int main(int argc, char *argv[])
    {
        int sock, clntSock;																/*  Socket descriptor */
        //int dataSock;															/* Data sockeet Descriptor*/
        int i;
    	int processID;
        struct sockaddr_in ftpServAddr;											/*  server address */
        struct hostent *hp;
        unsigned short ftpServPort;												/*  server port */
        char *servIP;															/*  Server IP address */
        char *username;															/* User Name for ftp server */
        char *pwd;																/* Password for connecting to ftp server*/
        char *fileName;															/*  FileName to get from the server */
        char *command;
        char *file;
        char *p;
        char *c;
    	char *path;
    	int count;
        char echoBuffer[RCVBUFSIZE];											/* Buffer for echo string */
        unsigned int echoStringLen;												/* Length of string to echo */
        int bytesRcvd, totalBytesRcvd;											/* Bytes read in single recv()*/
        ftpServPort = 21;
        char tmpHost[100];
        int tmpPort;
        char buf[5120];
         unsigned int PORTBUFFER;
         char * hostname;
    	 servIP = argv[1] ;	/* First arg' server IP address */				
    
          /* Second arg' Username */
    	  username = argv[2];
          													/* Third arg' Password */
    	  pwd =  argv[3];
          printf("Creating Socket");
          
           struct sigaction sa; /* deal with signals from dying children! */
    	   int yes = 1;
    //int x = argc;
     // fprintf(stderr, "number of arguments passed %i x");
    
    	  if (argc< 4) /* Test for correct number of arguments */
    		{
    			fprintf(stderr, "Usage: %s <Server IP> <UserName> <Password> <File-to-download> \n",
    			argv[0]);
    			exit(1);
    		}
    		//file = argv[4];
    		//path = argv[5];
    	    //int x;
                //for(x=1;x<(argc-3);x++)
                 // {
    	//	fileName = argv[3+x];
                    //printf(fileName);
             //      }
           gethostname(hostname, PORTBUFFER);
         // if ((hp = gethostbyname(hostname)) == 0) {
          //perror("gethostbyname");
          //return -1;
       //}
    	/* Create a reliable, stream socket using TCP */
    	if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
         	 DieWithError(" socket () failed") ;
    
    /* Construct the server address structure */
    	memset(&ftpServAddr, 0, sizeof(ftpServAddr));							/* Zero out structure */
    	ftpServAddr.sin_family         = AF_INET;								/* Internet address family */
    	ftpServAddr.sin_addr.s_addr 	= inet_addr(servIP);					/* Server IP address */
    	ftpServAddr.sin_port           = htons(ftpServPort);					/* Server port */
    
    /* Establish the connection to the ftp server */
            if (connect(sock, (struct sockaddr *) &ftpServAddr, sizeof(ftpServAddr)) < 0)
               DieWithError(" connect () failed") ;
            else
    	  printf("Connection Successful");
    
    	//sleep(1);
    	if(ftpRecvResponse(sock,buf)==1) 
    	 {
              printf("Reached Here");
    	  if(strncmp(buf,"220",3)==0) 
    	   {
    	    printf("Sending UserName");
    	    printf(username);
    	    if(ftpNewCmd(sock,buf,"USER",username)==1);
    	     {
    	      if(ftpRecvResponse(sock, buf) == 1)
      	       {
     	        if(strncmp(buf,"331",3)==0)
    	         {
    	  	       printf("Sending Password");
    	           if(ftpNewCmd(sock, buf, "PASS", pwd) == 1)
     	            {
      	             if(ftpRecvResponse(sock, buf) == 1)
      	              {
       	               if(strncmp(buf, "230",3)==0)
        	               {
    			   
    			    for(i=1; i<(argc-3);i++)
    			    {
    				fileName = argv[3+i];
    				if ((processID = fork()) < 0)
    				{
    				 DieWithError("HERE");
    				 }
    				else if(processID == 0)//this is the child
    				 {
                                       if(ftpNewCmd(sock, buf, "PASV", "") == 1)
    			           {
                                         if(ftpRecvResponse(sock, buf) == 1)
          	       		             {
           		             	      if(strncmp(buf, "227",3)==0)
            	              	      {
    					ftpConvertAddr(buf,tmpHost,&tmpPort);
    					if(ftpNewCmd(sock,buf,"RETR",fileName)==1)
    					{
    					 
    					 ftpSendFile(fileName,tmpHost,tmpPort);
    					 if(ftpRecvResponse(sock,buf)==1)
    					 {
    					  if(strncmp(buf,"150",3)==0)
    					  {
    					   if(ftpRecvResponse(sock, buf)==1)
    					   {
                                                printf("\nReceive Response\n");
    					   if(strncmp(buf,"226",3)==0)
    					   {
    					     printf("Transfer Completed");
    					    //close(sock);
      					   //exit(0);
    					   }
            	 			  }
           				         }
          	      			        }
         	    			       }
    	   			      }
    	  			     }
    	 			    }
    				   }
    				else //this is the parent process
    				 {
    				   	/* Signal handler stuff */
    			   		sa.sa_handler = sigchld_handler;
    			   		/* reap all dead processes */
    			   		sigemptyset( &sa.sa_mask);
    			   		sa.sa_flags = SA_RESTART;
    			   		if( sigaction( SIGCHLD, &sa, NULL) == -1)
    			   		 {
    			     		  perror( "Server sigaction");exit( 1);
    			    		  }
    				   }
    				  }	//ftpSendFile(buf, "saraswati", 20);
     			         } 	//close(sock);
      			        }	//exit(0);
    			       }
    		              }
    			     }
    			    }
    			   }
    			  }	
    /* ToDo: Put Code for writing file stats(size, name, time taken to download etc)*/
    	//wait();
    	close(sock);
      	exit(0);
    }
    int ftpSendFile(char * buf, char * host, int port) {
       int sd;
       struct sockaddr_in pin;
       struct hostent *hp;
       char * FileName;
       FileName = buf;
       if ((hp = gethostbyname(host)) == 0) {
          perror("gethostbyname");
          return -1;
       }
       memset(&pin, 0, sizeof(pin));
       pin.sin_family = AF_INET;
       pin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
       pin.sin_port = htons(port);
       if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
          perror("socket");
          return -1;
       }
       if (connect(sd,(struct sockaddr *)  &pin, sizeof(pin)) == -1) {
          perror("connect");
          return -1;
       }
       if(send(sd, buf, strlen(buf), 0) == -1) {
          perror("send");
          return -1;
       }
       	FILE *fd;
    	char buff[4096];
    	buff[4095] = '\0';
    
      	int n_bytes;
    	int n_recv=0;
            printf("\n**********FileName**********\n");
            printf(FileName);
            printf("***********END***************\n");
    	fd = fopen(FileName, "wb");
    		
    		if (fd == NULL) {
    		//if (verbose) {
    		printf("--[ Error: Unable to open '%s' in ftp_get function\n", FileName);
    		//}
    
    		//free(buffer);
    		
    		return -1;
    		}
    
    	//time(&start);
    
    	while (1) {
    
    		//usleep(150);
    		n_recv = recv(sd, buff, 4094, 0);
    		n_bytes = fwrite(buff, sizeof(char), n_recv, fd);
    		
    		if (n_recv == 0) {
    			break;
    		}
    
    		n_recv = 0;
    
    		memset(buff, 0x0, n_bytes);
    		
    		}
    
    	
    	fclose(fd);
    printf("closing client socket");
       close(sd); /*//close the socket*/
       return 0;
    }
    int ftpRecvResponse(int Sock, char * buf) {
       int i;
    
       if (recv(Sock, buf, 1024, 0) == -1) {//receive the data
          perror("recv");
          return 0;;
       }
       for(i=(strlen(buf) - 1);i>0;i--) {
          if(buf[i]=='.' || buf[i]=='\r') { 
             buf[i+1]='\0';
             break;
          }
       }
       printf("%s\n",buf); //print response to the screen
       return 1;
    }
    
    
    
    
    int ftpNewCmd(int Sock, char * buf, char * cmd, char * param) {
       strcpy(buf,cmd);
       if(strlen(param) > 0) {
          strcat(buf," ");
          strcat(buf,param);
       }
       strcat(buf,"\r\n");
       printf("*%s",buf); //print the cmd to the screen
       if(send(Sock, buf, strlen(buf), 0) == -1) {
          perror("send");
          return 0;
       }
       //clear the buffer
    //fflush(buf);
       return 1;
    }
    
    int ftpConvertAddr(char * buf, char * hostname, int * port) {
       unsigned int i,t=0;
       int flag=0,decCtr=0,tport1,tport2;
       char tmpPort[6];
       //example data in quotes below:
       //"227 Listening on (149,122,52,162,4,20)"
       //4 * 256 + 20 = 1044
       for(i=0;i<strlen(buf);i++) {
          if(buf[i]=='(') {
             flag = 1;
             i++;
          }
          if(buf[i]==')') {
             hostname[t]='\0';
             break;
          }
          if(flag==1) {
             if(buf[i] != ',') {
                hostname[t]=buf[i];
                t++;
             } else {
                hostname[t]='.';
                t++;
             }
          }
       }
       t=0;
       for(i=0;i<strlen(hostname);i++) {
          if(hostname[i]=='.')
             decCtr++;
          if(decCtr==4 && hostname[i]!='.') {
             tmpPort[t]=hostname[i];
             t++;
             if(hostname[i+1]=='.') {
                tmpPort[t]='\0';
                tport1=atoi(tmpPort);
                t=0;
             }
          }
          if(decCtr==5 && hostname[i]!='.') { 
             tmpPort[t]=hostname[i];
             t++;
             if(hostname[i+1]=='\0') {
                tmpPort[t]='\0';
                tport2=atoi(tmpPort);
                t=0;
             }
          }
       }
       *port = tport1 * 256 + tport2;
       decCtr=0;
       for(i=0;i<strlen(hostname);i++) {
          if(hostname[i]=='.') {
             decCtr++;
          }
          if(decCtr>3)
             hostname[i]='\0';
       }
       return 0;
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    And you have no problem following 20 nested levels of code with crap formatting?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    10
    Quote Originally Posted by Salem View Post
    And you have no problem following 20 nested levels of code with crap formatting?
    I think you have not read the post in entirety, I already said I am newbie to socket programming.
    I you cannot help, please not mind posting.
    Thanks,

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Damn right I haven't read it all.
    Not many other people are going to either.

    We've all got a limited time to help, and what isn't going to happen is us spending time formatting a whole mess of code before we can even begin to look at the problem.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Jan 2011
    Posts
    1
    Hi Dynamo,
    can I have the ftp server code that communicate with this ftp client which you are posting.
    I want to know how the server side maintain the password.
    tq

  6. #6
    Registered User
    Join Date
    Mar 2010
    Posts
    68

    sockets

    firstly, networking is mostly a serial process, meaning only one thing should be going on at a time. Especially, for a single connection to an ftp server. For that single connection you should only be doing one thing at a time, then doing the next. I don't even think the ftp server would allow you to have multiple downloads from a single connection in this manner.

    When ever programming any new program, it is important to try and start small then continually build off of that. So, try connecting, do a directory listing, and download a file. Then, try to add functionality to that.


    Hopefully that answers your questions.

    Also, code formatting is especially important. I started formatting your code how I would, but stopped. The nested if statements need to be taken out. I cant say what should go there because I would suggest rewriting the entire program; however, when I started programming I was just like you, so I am not saying I was better than you. In any case, rewrite your code for ease of reading. Try creating some function calls and use those, like

    bool ConnectToFtp(const char* addres, const char* login, const char* pass);
    bool ListDirectory();
    bool DisconnectFromFtp();
    bool DownloadFile(const char* serverfilename, const char clientfilename);

    Code:
    	if(ftpRecvResponse(sock,buf)==1) {
    		printf("Reached Here");
    		if(strncmp(buf,"220",3)==0) {
    			printf("Sending UserName");
    			printf(username);
    			if(ftpNewCmd(sock,buf,"USER",username)==1){
    				if(ftpRecvResponse(sock, buf) == 1){
    					if(strncmp(buf,"331",3)==0){
    						printf("Sending Password");
    						if(ftpNewCmd(sock, buf, "PASS", pwd) == 1){
    							if(ftpRecvResponse(sock, buf) == 1){
    								if(strncmp(buf, "230",3)==0){
    									for(i=1; i<(argc-3);i++){
    										fileName = argv[3+i];
    										if ((processID = fork()) < 0){
    											DieWithError("HERE");
    										}else if(processID == 0) {//this is the child

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Socket Programming Problem!!!!
    By bobthebullet990 in forum Networking/Device Communication
    Replies: 2
    Last Post: 02-21-2008, 07:36 PM
  2. multiple forks, pipes?
    By alcaseltz in forum C Programming
    Replies: 2
    Last Post: 10-26-2007, 07:07 AM
  3. Headers that use each other
    By nickname_changed in forum C++ Programming
    Replies: 7
    Last Post: 10-03-2003, 04:25 AM
  4. Linux: Sample: Client - Server (Connection Error)
    By zahid in forum Networking/Device Communication
    Replies: 3
    Last Post: 09-07-2003, 05:32 PM
  5. Multiple Client Connections
    By (TNT) in forum Windows Programming
    Replies: 1
    Last Post: 04-06-2002, 11:04 PM