FTP 下载客户端 C语言实现

时间:2021-08-02 08:32:45
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <sys/stat.h>
#include <fcntl.h>

#include <errno.h>


/*
 * FTP Retrun Code
 * 200 SUCCESS, 202 command not execute
 * 220 ready, 230 login
 * 250 file finish
 */

int gCmdSock;
int gDataSock;
char gRevBuf[512];

// ftp cmd
static int ftpcmd(const char *s1, const char * s2)
{
        int iRet;

        char cmdBuf[256] = {0};
        if(s1)
        {
                sprintf(cmdBuf, (s2?"%s %s \r\n":"%s %s\r\n"+3), s1, s2);
                send(gCmdSock, cmdBuf, strlen(cmdBuf), 0);
        }

        do{
                strcpy(gRevBuf, "EOF");
                if(recv(gCmdSock, gRevBuf, sizeof(gRevBuf)-2, 0 ) < 0)
                {
                        return 0;
                }
        }while(!isdigit(gRevBuf[0]) || gRevBuf[3] != ' ');
        gRevBuf[3] = '\0';
        iRet = atoi(gRevBuf);
        gRevBuf[3] = ' ';

        return iRet;
}

void printcmd( const char * s1, const char * s2 )
{
        char cmdBuf[256] = {0};
        char gRevBuf[512] = {0};
        if(s1)
        {
                sprintf(cmdBuf, (s2?"%s %s \r\n":"%s %s\r\n"+3), s1, s2);
                send(gCmdSock, cmdBuf, strlen(cmdBuf), 0);
        }

        do{
                strcpy(gRevBuf, "EOF");
                if(recv(gCmdSock, gRevBuf, sizeof(gRevBuf)-2, 0 ) < 0)
                {
                        return;
                }
                printf("%s", gRevBuf);
        }while(1);
}

void download( char * local_path, char * server_path )
{
        int rd;
        char * buf_ptr;
        int port_num;
        int fd_local;
        struct sockaddr_in ftpData_addr;
        char buffer[4096] = {0};

        // Get the port of data tranfor
        if(ftpcmd("PASV", NULL)!=227)
        {
                fprintf(stderr, "Chang passive mode error\n");
                return;
        }
        printf("Enter passive mode\n");
        printf("%s\n", gRevBuf);

        buf_ptr = strrchr(gRevBuf, ')');
        if( buf_ptr )
                *buf_ptr = '\0';

        buf_ptr = strrchr(gRevBuf, ',');
        *buf_ptr = '\0';
        port_num = atoi(buf_ptr + 1);

        buf_ptr = strrchr(gRevBuf, ',');
        *buf_ptr = '\0';
        port_num += atoi(buf_ptr + 1) * 256;
        printf("The data socket port is %d.\n", port_num);

        // connent the data socket
        memset(&ftpData_addr, 0, sizeof(ftpData_addr));
        ftpData_addr.sin_family = AF_INET;
        ftpData_addr.sin_addr.s_addr = inet_addr("192.168.0.104");
        ftpData_addr.sin_port = htons(port_num);

        gDataSock = socket(AF_INET, SOCK_STREAM, 0 );
        if(gDataSock < 0)
        {
                fprintf(stderr, "Create data socket error.\n");
                return;
        }

        if(connect(gDataSock, (struct sockaddr *)&ftpData_addr, sizeof(ftpData_addr)) < 0)
        {
                fprintf(stderr, "Connect data socket error.\n");
                return;
        }

        if(ftpcmd("RETR", server_path) > 150)
        {
                fprintf(stderr, "RETR data error.\n");
                return;
        }

        fd_local = open( local_path, (O_CREAT | O_TRUNC | O_WRONLY) );
        if(fd_local < 0)
        {
                fprintf(stderr, "open local file error.\n");
                return;
        }

        while(1)
        {
                rd = recv(gDataSock, buffer, 4096, 0);
                printf("rd=%d\n",rd);
                if( rd <= 0 )
                        break;
                write(fd_local, buffer, rd);
                //sleep(1);
        }

        if (ftpcmd(NULL, NULL) != 226) {
                fprintf(stderr, "Trans file error.\n");
                return;
        }

        close(fd_local);
        close(gDataSock);
}

int main()
{
        struct sockaddr_in ftpSrv_addr;
        int iRet;

        // Create socket
        gCmdSock = socket(AF_INET, SOCK_STREAM, 0);
        if(gCmdSock < 0)
        {
                fprintf(stderr, "Create socket error\n");
                exit(1);
        }

        // Connect to Ftp server
        memset(&ftpSrv_addr, 0, sizeof(ftpSrv_addr));
        ftpSrv_addr.sin_family = AF_INET;
        ftpSrv_addr.sin_addr.s_addr = inet_addr("192.168.0.104");
        ftpSrv_addr.sin_port = htons(21);

        if(connect(gCmdSock, (struct sockaddr *)&ftpSrv_addr, sizeof(ftpSrv_addr)) < 0)
        {
                fprintf(stderr, "Connect socket error\n");
                exit(2);
        }

        // Check if connect OK
        if( ftpcmd(NULL, NULL) !=220 )
        {
                fprintf(stderr, "FTP server not ready error\n");
                exit(3);
        }
        printf("FTP READY!\n");
        // Login
        switch(ftpcmd("USER", "software"))
        {
                case 230:
                        break;
                case 331:
                        if( ftpcmd("PASS", "password")!= 230 )
                        {
                                fprintf(stderr, "Wrong password\n");
                                exit(4);
                        }
                        break;
                default:
                        fprintf(stderr, "Wrong user\n");
                        exit(4);
        }
        // Tansfor mode
        ftpcmd("TYPE I", NULL);
        printf("Login Success!\n");

        download("upload.iso", "/test/upload.iso");

        ftpcmd("QUIT", NULL);
        close(gCmdSock);
        return 0;
}