• Linux/Unix 系统编程 — FTP客户端


    尊重作者劳动成果,转载请注明出处,谢谢!

    1. ftp.h

    #ifndef ftp_H
    #define ftp_H
    
    #include "types.h"
    #include "socket.h"
    
    #ifdef __cplusplus
    extern "C"
    {
    #endif
        int ftp_login(const char *servIp, unsigned short port, const char *user, const char *password);
        boolean ftp_quit(int sockfd);
        boolean ftp_getCurrentDirectory(int sockfd, char *directory);
        boolean ftp_changDirectory(int sockfd, const char *directory);
        boolean ftp_changDirectoryUp(int sockfd);
        boolean ftp_createDirectory(int sockfd, const char *directory);
        boolean ftp_fileList(int sockfd);
        boolean ftp_download(int sockfd, const char *remoteFileName, const char *filePath);
        boolean ftp_upload(int sockfd, const char *remoteFileName, const char *filePath);
    #ifdef __cplusplus
    }
    #endif
    
    #endif

    2. ftp.c

    #include "ftp.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    
    static unsigned short strToHostAndPort(const char *str, char *host)
    {
        int addr[6];
        sscanf(str, "%*[^(](%d,%d,%d,%d,%d,%d)", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]);
    
        bzero(host, strlen(host));
        sprintf(host, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
    
        unsigned short port;
        port = addr[4] * 256 + addr[5];
        return port;
    }
    
    static boolean recvAndCheck(int sockfd, const char *code)
    {
        char buf[1024] = {0};
        int nrecv = recv(sockfd, buf, 1024, 0);
        if (nrecv <= 0)
            return False;
    
        printf("%s
    ", buf);
        return strncmp(buf, code, 3) == 0 ? True : False;
    }
    
    static boolean ftp_sendCommandWithResult(int sockfd, const char *cmd, const char *arg, const char *code, char *result)
    {
        if (sockfd == INVALID_SOCKET)
            return False;
    
        char *cmdBuf = (char *)malloc(strlen(cmd) + strlen(arg) + 10);
        sprintf(cmdBuf, "%s %s
    ", cmd, arg);
        int cmdBufSize = strlen(cmdBuf);
    
        int nsend = send(sockfd, cmdBuf, cmdBufSize, 0);
        free(cmdBuf);
        if (nsend != cmdBufSize)
            return False;
    
        char buf[1024] = {0};
        int nrecv = recv(sockfd, buf, 1024, 0);
        printf("%s
    ", buf);
        if (nrecv <= 0)
            return False;
    
        if (result != NULL)
            strcpy(result, buf);
    
        return strncmp(buf, code, 3) == 0 ? True : False;
    }
    
    static boolean ftp_sendCommand(int sockfd, const char *cmd, const char *arg, const char *code)
    {
        return ftp_sendCommandWithResult(sockfd, cmd, arg, code, NULL);
    }
    
    //使用被动模式,并返回数据端口的文件描述符
    static int ftp_uesPasvMode(int sockfd)
    {
        if (sockfd == INVALID_SOCKET)
            return False;
    
        char buf[1024] = {0};
    
        //227 Entering Passive Mode (192,168,1,100,191,160).
        if (!ftp_sendCommandWithResult(sockfd, "PASV", "", "227", buf))
            return False;
    
        char data_host[32] = {0};
        unsigned short data_port;
        data_port = strToHostAndPort(buf, data_host);
    
        return createTcpClient(data_host, data_port);
    }
    
    //ftp登录
    int ftp_login(const char *servIp, unsigned short port, const char *user, const char *password)
    {
        int sockfd = createTcpClient(servIp, port);
        if (sockfd == INVALID_SOCKET)
            return -1;
    
        //220 (vsFTPd 3.0.3)
        if (!recvAndCheck(sockfd, "220"))
        {
            close(sockfd);
            return INVALID_SOCKET;
        }
    
        //331 Please specify the password.
        if (!ftp_sendCommand(sockfd, "USER", user, "331"))
        {
            close(sockfd);
            return INVALID_SOCKET;
        }
    
        //230 Login successful.
        if (!ftp_sendCommand(sockfd, "PASS", password, "230"))
        {
            close(sockfd);
            return INVALID_SOCKET;
        }
    
        //200 Switching to Binary mode.
        if (!ftp_sendCommand(sockfd, "TYPE", "I", "200"))
        {
            close(sockfd);
            return INVALID_SOCKET;
        }
    
        return sockfd;
    }
    
    //ftp注销
    boolean ftp_quit(int sockfd)
    {
        if (sockfd == INVALID_SOCKET)
            return False;
    
        //221 Goodbye.
        if (!ftp_sendCommand(sockfd, "QUIT", "", "221"))
            return False;
    
        close(sockfd);
        return True;
    }
    
    //ftp获取当前工作目录
    boolean ftp_getCurrentDirectory(int sockfd, char *directory)
    {
        if (sockfd == INVALID_SOCKET)
            return False;
    
        //257 "/root" is the current directory
        char buf[1024];
        if (!ftp_sendCommandWithResult(sockfd, "PWD", "", "257", buf))
            return False;
    
        int i = 0;
        char *ptr = buf + 5;
        while (*ptr != '"')
        {
            directory[i++] = *ptr;
            ptr++;
        }
    
        directory[i] = '';
        return True;
    }
    
    //ftp更改当前工作目录
    boolean ftp_changDirectory(int sockfd, const char *directory)
    {
        if (sockfd == INVALID_SOCKET)
            return False;
    
        //250 Directory successfully changed.
        return ftp_sendCommand(sockfd, "CWD", directory, "250");
    }
    
    //ftp更改当前工作目录为上一级目录
    boolean ftp_changDirectoryUp(int sockfd)
    {
        if (sockfd == INVALID_SOCKET)
            return False;
    
        //250 Directory successfully changed.
        return ftp_sendCommand(sockfd, "CDUP", "", "250");
    }
    
    //ftp创建文件夹
    boolean ftp_createDirectory(int sockfd, const char *directory)
    {
        if (sockfd == INVALID_SOCKET)
            return False;
    
        //257 "directory" created
        return ftp_sendCommand(sockfd, "MKD", directory, "257");
    }
    
    //ftp文件列表
    boolean ftp_fileList(int sockfd)
    {
        if (sockfd == INVALID_SOCKET)
            return False;
    
        int data_fd = ftp_uesPasvMode(sockfd);
        if (data_fd == INVALID_SOCKET)
            return False;
    
        //150 Here comes the directory listing.
        if (!ftp_sendCommand(sockfd, "LIST", "", "150"))
        {
            close(data_fd);
            return False;
        }
    
        int bufSize = 1024;
        char buf[1024] = {0};
        int nrecv;
        while ((nrecv = recv(data_fd, buf, bufSize, 0)) > 0)
        {
            //drwx------    2 0        0               0 Sep 24 05:51 123
            //-rwx------    1 0        0           34980 Aug 20 04:28 devserv
            //-rw-------    1 0        0              30 Aug 20 03:58 devserv.conf
            printf("%s
    ", buf);
        }
    
        close(data_fd);
    
        //226 Directory send OK.
        return recvAndCheck(sockfd, "226");
    }
    
    //ftp下载文件
    boolean ftp_download(int sockfd, const char *remoteFileName, const char *filePath)
    {
        if (sockfd == INVALID_SOCKET)
            return False;
    
        int data_fd = ftp_uesPasvMode(sockfd);
        if (data_fd == INVALID_SOCKET)
            return False;
    
        //150 Opening BINARY mode data connection for "remoteFileName" (n bytes)
        if (!ftp_sendCommand(sockfd, "RETR", remoteFileName, "150"))
        {
            close(data_fd);
            return False;
        }
    
        int file_fd = open(filePath, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
        if (file_fd < 0)
        {
            close(data_fd);
            return False;
        }
    
        int bufSize = 4096;
        char buf[4096];
        int nread;
        while ((nread = recv(data_fd, buf, bufSize, 0)) > 0)
        {
            write(file_fd, buf, nread);
        }
    
        close(file_fd);
        close(data_fd);
    
        //226 Transfer complete.
        return recvAndCheck(sockfd, "226");
    }
    
    //ftp上传文件
    boolean ftp_upload(int sockfd, const char *remoteFileName, const char *filePath)
    {
        if (sockfd == INVALID_SOCKET)
            return False;
    
        if (access(filePath, F_OK) != 0)
            return False;
    
        int data_fd = ftp_uesPasvMode(sockfd);
        if (data_fd == INVALID_SOCKET)
            return False;
    
        //150 Ok to send data.
        if (!ftp_sendCommand(sockfd, "STOR", remoteFileName, "150"))
        {
            close(data_fd);
            return False;
        }
    
        int file_fd = open(filePath, O_RDONLY);
        if (file_fd < 0)
        {
            close(data_fd);
            return False;
        }
    
        int bufSize = 4096;
        char buf[4096];
        int nread;
        while ((nread = read(file_fd, buf, bufSize)) > 0)
        {
            send(data_fd, buf, nread, 0);
        }
    
        close(file_fd);
        close(data_fd);
    
        //226 Transfer complete
        return recvAndCheck(sockfd, "226");
    }
  • 相关阅读:
    GetForegroundWindow 与 GetActiveWindow 的区别 回复 "delphier" 的问题
    给 TStringGrid 添加鼠标拖动功能 回复 "dxx" 的问题
    Delphi 的编译指令(3): 常用的预定义条件标识符
    Delphi 的编译指令(1): $DEFINE、$UNDEF、$IFDEF、$ELSE、$ENDIF
    用多媒体库 Bass.dll 播放 mp3 [17] : 如何从内存流播放 回复 "小李子子" 的问题
    Delphi 的编译指令(4): 编译指令全表(未完)
    窗口跟随 回复 "heyongan" 的问题
    字符串转换到指定格式的宽字符 回复 "厨师" 的问题
    Dll 使用 PChar 参数的小例子 回复 "linximf" 的问题
    上周热点回顾(5.286.3)
  • 原文地址:https://www.cnblogs.com/chenyuxin/p/15330414.html
Copyright © 2020-2023  润新知