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"
Appreciate if someone can help me here.
The code is a bit messy however it works for downloading a single file from the ftp server
Expand|Select|Wrap|Line Numbers
- /*******************************************************************************
- 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>
- #include "ftpClient1.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);
- void debug(int debugLevel, const char * debugDesc, const char * debugStr);
- /************************************
- 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");
- //debug(1, "Creating Socket", "");
- struct sigaction sa; /* deal with signals from dying children! */
- int yes = 1;
- 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);
- }
- gethostname(hostname, PORTBUFFER);
- /* 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);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- /* ToDo: Put Code for writing file stats(size, name, time taken to download etc)*/
- close(sock);
- exit(0);
- }