【学习笔记】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];// 初始化libcurlcurl_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 = ""; // 服务器IPconst 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]; // 删除文件命令// 初始化libcurlcurl_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;
}