【学习笔记】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;
}
相关推荐
JanelSirry9 分钟前
Windows下GDAL Java环境搭建全攻略
笔记·eclipse·intellij-idea·gdal
leo_yu_yty31 分钟前
Mysql DBA学习笔记(主从复制)
学习·mysql·dba
共饮一杯无1 小时前
在 Windows 系统上怎么使用rabbitmq相关命令,比如:rabbitmqctl list_queues 命令
windows·rabbitmq·rabbitmq命令
koo3641 小时前
李宏毅机器学习笔记15
人工智能·笔记·机器学习
明明真系叻1 小时前
量子计算学习笔记(2)
笔记·学习·量子计算
哲Zheᗜe༘1 小时前
了解学习Nginx反向代理与缓存功能
学习·nginx·缓存
sswithyou2 小时前
TCP的学习
网络协议·学习·tcp/ip
BreezeJuvenile2 小时前
外设模块学习(3)——28BYJ-48步进减速电机
stm32·学习·步进电机·外设模块
苦逼大学生被编程薄纱3 小时前
C++ 容器学习系列|vector 核心知识全解析,铺垫下一期模拟实现
开发语言·c++·学习
DKPT3 小时前
JVM栈溢出时如何dump栈信息?
java·jvm·笔记·学习·spring