【学习笔记】FTP库函数学习

【学习笔记】FTP库函数学习

FTP基本指令步骤

1、初始化会话句柄:CURL *curl = curl_easy_init();

2、设置会话选项: 设置服务器地址,设置登录用户和密码

curl_easy_setopt(curl, CURLOPT_URL, ftp_server);

curl_easy_setopt(curl, CURLOPT_USERNAME, user);

curl_easy_setopt(curl, CURLOPT_PASSWORD, pass);

启用被动模式(兼容性更好)

curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 1L);

开启调试模式,查看详细交互

curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

3、执行会话操作:CURLcode res = curl_easy_perform(curl);

注意:执行会话操作之前,可以将要执行的命令先放到命令序列中,先放先执行。命令序列:struct curl_slist *cmd_list = NULL

复制代码
 12     char cwd_cmd[256];    // 切换目录命令 
 13     char delete_cmd[256]; // 删除文件命令
 24     // 构建切换目录命令(CWD)和删除命令(DELE) 
 25     snprintf(cwd_cmd, sizeof(cwd_cmd), "CWD %s", target_dir); 
 26     snprintf(delete_cmd, sizeof(delete_cmd), "DELE %s", filename); 
 40     // 添加命令序列:先切换目录,再删除文件 
 41     cmd_list = curl_slist_append(cmd_list, cwd_cmd);    // 第一步:切换到目标目录 
 42     cmd_list = curl_slist_append(cmd_list, delete_cmd); // 第二步:删除文件 
 43     curl_easy_setopt(curl, CURLOPT_POSTQUOTE, cmd_list); 
 44  
 45     // 执行操作 
 46     res = curl_easy_perform(curl); 

4、释放会话资源:curl_easy_cleanup(curl); // 释放资源,避免内存泄漏

注意:在大型项目中,curl_global_init 只需要调用一次 ,且应放在程序生命周期的早期(初始化阶段),配合 curl_global_cleanup 在程序退出时释放资源。

FTP基本指令&日志

服务器日志:

-virtual-machine:/var/log$ sudo tail -f /var/log/vsftpd.log

查看服务器是否开启:

sudo systemctl status vsftpd

重启服务器服务:

sudo systemctl restart vsftpd

重启之后可以查看日志:

sudo journalctl -u vsftpd.service # 查看vsftpd的详细日志

手动运行查看错误日志:

sudo /usr/sbin/vsftpd /etc/vsftpd.conf

防火墙对某个端口的处理:

-virtual-machine:/etc$ sudo ufw status | grep 59924

系统对某个端口的监听:

-virtual-machine:/etc$ sudo netstat -tunlp | grep 59924

开放端口:开放端口: sudo ufw allow 123/udp sudo ufw reload

##注意事项:

1、配置文件注意事项:/etc/vsftpd.conf文件中不可以有多余的空格,都则编译报错。

2、查看防火墙开放的端口,确保被动模式下服务器开的端口范围都是开放的:sudo ufw status

3、一般采用被动模式:客户端自己给一个端口去连接服务器,服务器支持被动模式,并且需要开放一定数量的端口来做交互。就是上面所说的防火墙开放的50000:50010端口。

工作原理

  • 客户端连接到服务器的 21 端口(默认的控制连接端口)。
  • 服务器返回状态码 220,表示服务已就绪。
  • 客户端发送用户名(USER 命令),服务器返回 331,表示需要密码。
  • 客户端发送密码(PASS 命令),服务器返回 230,表示登录成功。

FTP 支持两种模式传输文件:

  • 主动模式:服务器主动连接到客户端的数据端口。
  • 被动模式:客户端连接到服务器的数据端口。

测试

登录测试:

复制代码
#include <stdio.h>
#include "curl.h"

// 回调函数:处理服务器返回的信息(如登录成功提示)
size_t ftp_response_callback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    printf("服务器响应: %.*s\n", (int)realsize, (char *)contents);
    return realsize;
}

// FTP登录函数
int ftp_login(const char *server_ip, const char *username, const char *password) {
    CURL *curl;
    CURLcode res;
    char ftp_url[128];

    // 初始化libcurl
    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();

    if (curl) {
        // 构建FTP服务器URL(仅登录,不操作文件)
        snprintf(ftp_url, sizeof(ftp_url), "ftp://%s/", server_ip);

        // 设置FTP服务器地址
        curl_easy_setopt(curl, CURLOPT_URL, ftp_url);

        // 设置登录用户名和密码
        curl_easy_setopt(curl, CURLOPT_USERNAME, username);
        curl_easy_setopt(curl, CURLOPT_PASSWORD, password);

        // 启用被动模式(EPSV 是现代被动模式,优先使用)
        curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 1L);

        // 设置服务器响应的回调函数(用于显示登录结果)
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ftp_response_callback);

        // 启用详细输出(可选,用于调试)
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

        // 执行登录操作(本质是建立连接并验证身份)
        printf("正在连接到FTP服务器: %s...\n", server_ip);
        res = curl_easy_perform(curl);

        // 检查登录结果
        if (res != CURLE_OK) {
            fprintf(stderr, "登录失败: %s\n", curl_easy_strerror(res));
            curl_easy_cleanup(curl);
            curl_global_cleanup();
            return 1;
        } else {
            printf("登录成功!已连接到FTP服务器: %s\n", server_ip);
        }

        // 清理资源
        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();
    return 0;
}

int main() {
    // 你的FTP服务器信息(与命令行登录一致)
    const char *server_ip = "";  // 服务器IP
    const char *username = "";       // 用户名
    const char *password = "";    // 密码

    // 执行FTP登录
    if (ftp_login(server_ip, username, password) != 0) {
        printf("FTP登录过程失败\n");
        return 1;
    }

    return 0;
}

删除文件:

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>

// 登录FTP,切换到指定目录并删除文件
int ftp_cd_and_delete(const char *ftp_server, const char *target_dir, 
                      const char *filename, const char *user, const char *pass) {
    CURL *curl = NULL;
    CURLcode res;
    struct curl_slist *cmd_list = NULL;
    char cwd_cmd[256];    // 切换目录命令
    char delete_cmd[256]; // 删除文件命令

    // 初始化libcurl
    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();
    
    if (!curl) {
        fprintf(stderr, "初始化curl失败\n");
        return 1;
    }

    // 构建切换目录命令(CWD)和删除命令(DELE)
    snprintf(cwd_cmd, sizeof(cwd_cmd), "CWD %s", target_dir);
    snprintf(delete_cmd, sizeof(delete_cmd), "DELE %s", filename);
    printf("准备执行切换目录命令: %s\n", cwd_cmd);
    printf("准备执行删除命令: %s\n", delete_cmd);
    
    // 设置FTP服务器地址(根目录)
    curl_easy_setopt(curl, CURLOPT_URL, ftp_server);
    // 设置登录信息
    curl_easy_setopt(curl, CURLOPT_USERNAME, user);
    curl_easy_setopt(curl, CURLOPT_PASSWORD, pass);
    // 启用被动模式(兼容性更好)
    curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 1L);
    // 开启调试模式,查看详细交互
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    
    // 添加命令序列:先切换目录,再删除文件
    cmd_list = curl_slist_append(cmd_list, cwd_cmd);    // 第一步:切换到目标目录
    cmd_list = curl_slist_append(cmd_list, delete_cmd); // 第二步:删除文件
    curl_easy_setopt(curl, CURLOPT_POSTQUOTE, cmd_list);

    // 执行操作
    res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
        fprintf(stderr, "操作失败: %s\n", curl_easy_strerror(res));
        curl_slist_free_all(cmd_list);
        curl_easy_cleanup(curl);
        curl_global_cleanup();
        return 1;
    }

    // 清理资源
    curl_slist_free_all(cmd_list);
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return 0;
}

int main() {
    // FTP服务器信息(请根据实际情况修改)
    const char *ftp_server = "";  // 服务器根目录
    const char *target_dir = "";  // 目标目录路径
    const char *username = "";
    const char *password = "";
    const char *target_file = "";  // 要删除的文件名

    // 步骤1:登录FTP,切换到目标目录,删除文件
    printf("1. 正在登录FTP服务器...\n");
    printf("2. 正在切换到目录: %s\n", target_dir);
    printf("3. 正在删除文件: %s\n", target_file);
    
    if (ftp_cd_and_delete(ftp_server, target_dir, target_file, username, password) != 0) {
        fprintf(stderr, "删除操作失败,程序退出\n");
        return 1;
    } else {
        printf("文件 %s 已成功删除\n", target_file);
    }

    return 0;
}
    printf("3. 正在删除文件: %s\n", target_file);
    
    if (ftp_cd_and_delete(ftp_server, target_dir, target_file, username, password) != 0) {
        fprintf(stderr, "删除操作失败,程序退出\n");
        return 1;
    } else {
        printf("文件 %s 已成功删除\n", target_file);
    }

    return 0;
}
相关推荐
初九之潜龙勿用2 分钟前
技术与情感交织的一生 (十一)
服务器·笔记·microsoft·印象笔记
序属秋秋秋14 分钟前
《C++初阶之STL》【模板参数 + 模板特化 + 分离编译】
开发语言·c++·笔记·学习·stl
Xueqian E22 分钟前
关于内核启动的optee: probe of firmware: optee failed with error -22 固件拉起失败的问题
笔记
le1616161 小时前
Groovy学习篇章一之—— GDK 探秘:Groovy如何给Java对象“开外挂”,让String也能“跑命令”!
android·java·学习
小王努力学编程1 小时前
【Linux系统编程】线程概念与控制
linux·服务器·开发语言·c++·学习·线程·pthread库
yiqiqukanhaiba2 小时前
STM32学习笔记2-GPIO的输出模式
笔记·stm32·学习
HaiQinyanAN2 小时前
【学习笔记】NTP时间同步验证
笔记·学习
图灵的白猫2 小时前
pipeline方法关系抽取--课堂笔记
笔记
phltxy2 小时前
常见排序的学习
java·学习·排序算法