当前位置: 首页 > wzjs >正文

网站改版中 模板搜公司名到公司的网站

网站改版中 模板,搜公司名到公司的网站,中国手机网站,安卓app市场文章目录 🧱 一、FTP 基础架构回顾🚀 二、FTP 客户端的核心结构🔗 三、连接与登录过程📌 1. ftp_create()📌 2. ftp_connect()📌 3. ftp_login() 📁 四、上传文件实现(ftp_upload_fi…

文章目录

    • 🧱 一、FTP 基础架构回顾
    • 🚀 二、FTP 客户端的核心结构
    • 🔗 三、连接与登录过程
      • 📌 1. `ftp_create()`
      • 📌 2. `ftp_connect()`
      • 📌 3. `ftp_login()`
    • 📁 四、上传文件实现(`ftp_upload_file()`)
      • 🚩 流程总览:
      • ✨ 细节讲解
        • ✅ 1. 判断 remote_path 是目录 or 文件路径
        • ✅ 2. 递归创建远程目录
        • ✅ 3. 进入 PASV 模式(被动模式)
        • ✅ 4. 发起数据连接(客户端主动连接)
        • ✅ 5. 发送 STOR 命令
        • ✅ 6. 发送文件内容(TCP)
    • 🔚 五、退出与清理
    • 📢 六、辅助函数详解
      • ✅ `send_command()`
      • ✅ `read_reply()`
    • 📌 七、完整上传流程演示(例子)
    • ✅ 总结:功能完整的 FTP 上传模块


这段代码实现了一个 FTP 客户端核心功能模块,可完成如下关键任务:

✅ 建立连接
✅ 登录认证
✅ 递归创建远程目录
✅ 上传文件(支持上传到目录)
✅ 退出登录


下面我将按照功能模块,详细讲解整个 FTP 上传流程的实现原理和关键函数


🧱 一、FTP 基础架构回顾

FTP 通信包括两个通道:

  • 控制通道(control channel):用于发送 FTP 命令和接收响应(TCP 21)
  • 数据通道(data channel):用于传输文件、目录等(通过 PASVPORT 创建)

本实现采用 PASV(被动模式) 建立数据通道,即客户端主动连接服务端开放的端口。


🚀 二、FTP 客户端的核心结构

typedef struct {int control_sock; // 控制通道 socketstruct sockaddr_in server_addr;
} FTPClient;

🔗 三、连接与登录过程

📌 1. ftp_create()

  • 创建控制通道 socket:socket(AF_INET, SOCK_STREAM, 0)
  • 配置远程 IP 和端口(默认 21)
  • 返回已初始化的 FTPClient 指针

📌 2. ftp_connect()

  • 使用 connect() 发起 TCP 控制连接
  • 成功后读取服务端欢迎信息(FTP 状态码应该是 220
read_reply(...) == 220 → 成功

📌 3. ftp_login()

  • 先发送用户名命令:USER xxx\r\n
    • 响应应为 331,表示继续输入密码
  • 再发送密码命令:PASS xxx\r\n
    • 响应应为 230,表示登录成功

📁 四、上传文件实现(ftp_upload_file()

🚩 流程总览:

→ 判断 remote_path 是目录还是完整路径
→ 如果是目录:拼接本地文件名
→ 递归创建远程目录(MKD)
→ 进入 PASV 模式,获取数据连接地址和端口
→ 发起数据连接(客户端连接服务端返回的地址/端口)
→ 发送 STOR 上传命令
→ 传输文件内容
→ 关闭数据连接并读取完成响应(226)

✨ 细节讲解

✅ 1. 判断 remote_path 是目录 or 文件路径
if (remote_path[strlen(remote_path) - 1] == '/') {// 是目录 → 拼接 local_file 的文件名
}

例:

local_file = "/home/user/a.txt"
remote_path = "upload/abc/"
→ final_remote_file = "upload/abc/a.txt"

✅ 2. 递归创建远程目录
ftp_create_remote_path(client, remote_dir);

内部调用:

MKD /upload
MKD /upload/abc
MKD /upload/abc/xyz

错误 550 表示已存在,也视作成功。


✅ 3. 进入 PASV 模式(被动模式)
send_command(..., "PASV\r\n");
read_reply(...); // 解析响应 227→ 解析返回的 IP 和端口:
"227 Entering Passive Mode (192,168,1,10,14,78)"
→ port = 14*256 + 78 = 3678

服务端会在该端口等待数据连接。


✅ 4. 发起数据连接(客户端主动连接)
data_sock = socket(...)
connect(data_sock, ...)

目标 IP = 控制连接 IP,端口 = PASV 返回的端口。


✅ 5. 发送 STOR 命令
STOR upload/abc/a.txt\r\n
→ 服务端响应 150:准备传输数据

✅ 6. 发送文件内容(TCP)
while (fread(...) > 0) {send(data_sock, ...);
}

成功发送完后:

  • 关闭 data_sock
  • 读取控制通道响应是否为 226 → 传输完成

🔚 五、退出与清理

ftp_quit(client);
→ 发送 QUIT\r\n,服务端应返回 221ftp_destroy(client);
→ 关闭 socket,释放内存

📢 六、辅助函数详解

send_command()

send(sock, command, strlen(command), 0);

发送命令字符串,例如:

"USER test\r\n"
"STOR /path/file.txt\r\n"

read_reply()

recv(sock, buffer, ...);
→ 返回第一段数字作为 FTP 响应码(例如 220331226

📌 七、完整上传流程演示(例子)

local_file = "/home/user/a.txt"
remote_path = "upload/test/"  // 目录

程序实际执行逻辑:

  1. 拼接路径 → upload/test/a.txt
  2. 创建路径:MKD /upload、/upload/test
  3. PASV 模式,服务端返回数据端口
  4. 建立数据连接
  5. STOR upload/test/a.txt
  6. 发送文件数据
  7. 等待 226 响应
  8. QUIT → 221

✅ 总结:功能完整的 FTP 上传模块

功能是否支持
控制连接建立
用户登录认证
被动模式数据传输
自动创建多级目录
上传任意路径文件
退出与资源释放

核心代码:

#include "ftpclient.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 1024// 内部函数声明
static int send_command(int sock, const char* command);
static int read_reply(int sock, char* buffer, size_t size);
static int ftp_create_dir(FTPClient* client, const char* remote_dir);// 创建客户端
FTPClient* ftp_create(const char* server_ip, int server_port) {FTPClient* client = (FTPClient*)malloc(sizeof(FTPClient));if (!client) return NULL;client->control_sock = socket(AF_INET, SOCK_STREAM, 0);if (client->control_sock < 0) {free(client);return NULL;}memset(&client->server_addr, 0, sizeof(client->server_addr));client->server_addr.sin_family = AF_INET;client->server_addr.sin_port = htons(server_port);inet_pton(AF_INET, server_ip, &client->server_addr.sin_addr);return client;
}void ftp_destroy(FTPClient* client) {if (client) {if (client->control_sock >= 0)close(client->control_sock);free(client);}
}int ftp_connect(FTPClient* client) {if (connect(client->control_sock, (struct sockaddr*)&client->server_addr, sizeof(client->server_addr)) < 0)return -1;char buffer[BUF_SIZE];return read_reply(client->control_sock, buffer, sizeof(buffer)) == 220 ? 0 : -1;
}int ftp_login(FTPClient* client, const char* username, const char* password) {char command[BUF_SIZE];char buffer[BUF_SIZE];snprintf(command, sizeof(command), "USER %s\r\n", username);if (send_command(client->control_sock, command) < 0) return -1;if (read_reply(client->control_sock, buffer, sizeof(buffer)) != 331) return -1;snprintf(command, sizeof(command), "PASS %s\r\n", password);if (send_command(client->control_sock, command) < 0) return -1;if (read_reply(client->control_sock, buffer, sizeof(buffer)) != 230) return -1;return 0;
}int ftp_upload_file(FTPClient* client, const char* local_file, const char* remote_path) {FILE* file = fopen(local_file, "rb");if (!file) return -1;char buffer[BUF_SIZE];// 处理 remote_file:判断是否是目录char final_remote_file[BUF_SIZE];if (remote_path[strlen(remote_path) - 1] == '/') {// 提取文件名const char* file_name = strrchr(local_file, '/');file_name = file_name ? file_name + 1 : local_file;snprintf(final_remote_file, sizeof(final_remote_file), "%s%s", remote_path, file_name);} else {strncpy(final_remote_file, remote_path, sizeof(final_remote_file));final_remote_file[sizeof(final_remote_file) - 1] = '\0';}// 提取目录路径并创建char remote_dir[BUF_SIZE];strncpy(remote_dir, final_remote_file, sizeof(remote_dir));remote_dir[sizeof(remote_dir) - 1] = '\0';char* last_slash = strrchr(remote_dir, '/');if (last_slash) {*last_slash = '\0';ftp_create_remote_path(client, remote_dir); // 忽略失败}// PASV 模式if (send_command(client->control_sock, "PASV\r\n") < 0) {fclose(file);return -1;}if (read_reply(client->control_sock, buffer, sizeof(buffer)) != 227) {fclose(file);return -1;}int ip1, ip2, ip3, ip4, p1, p2;sscanf(buffer, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)",&ip1, &ip2, &ip3, &ip4, &p1, &p2);int data_port = p1 * 256 + p2;int data_sock = socket(AF_INET, SOCK_STREAM, 0);if (data_sock < 0) {fclose(file);return -1;}struct sockaddr_in data_addr;memset(&data_addr, 0, sizeof(data_addr));data_addr.sin_family = AF_INET;data_addr.sin_port = htons(data_port);data_addr.sin_addr = client->server_addr.sin_addr;if (connect(data_sock, (struct sockaddr*)&data_addr, sizeof(data_addr)) < 0) {close(data_sock);fclose(file);return -1;}snprintf(buffer, sizeof(buffer), "STOR %s\r\n", final_remote_file);if (send_command(client->control_sock, buffer) < 0) {close(data_sock);fclose(file);return -1;}if (read_reply(client->control_sock, buffer, sizeof(buffer)) != 150) {close(data_sock);fclose(file);return -1;}size_t bytes_read;while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) {if (send(data_sock, buffer, bytes_read, 0) < 0) {close(data_sock);fclose(file);return -1;}}close(data_sock);fclose(file);return (read_reply(client->control_sock, buffer, sizeof(buffer)) == 226) ? 0 : -1;
}void ftp_quit(FTPClient* client) {send_command(client->control_sock, "QUIT\r\n");char buffer[BUF_SIZE];read_reply(client->control_sock, buffer, sizeof(buffer));
}// 创建路径:递归 MKD
int ftp_create_remote_path(FTPClient* client, const char* remote_path) {char path[BUF_SIZE];strncpy(path, remote_path, sizeof(path));path[sizeof(path) - 1] = '\0';char temp[BUF_SIZE] = {0};char* token = strtok(path, "/");while (token) {strcat(temp, "/");strcat(temp, token);ftp_create_dir(client, temp);  // 忽略失败token = strtok(NULL, "/");}return 0;
}static int ftp_create_dir(FTPClient* client, const char* remote_dir) {char buffer[BUF_SIZE];snprintf(buffer, sizeof(buffer), "MKD %s\r\n", remote_dir);if (send_command(client->control_sock, buffer) < 0) return -1;int code = read_reply(client->control_sock, buffer, sizeof(buffer));return (code == 257 || code == 550) ? 0 : -1; // 550 表示目录已存在
}static int send_command(int sock, const char* command) {return (send(sock, command, strlen(command), 0) == strlen(command)) ? 0 : -1;
}static int read_reply(int sock, char* buffer, size_t size) {int bytes_read = recv(sock, buffer, size - 1, 0);if (bytes_read <= 0) return -1;buffer[bytes_read] = '\0';return atoi(buffer);
}
http://www.dtcms.com/wzjs/803854.html

相关文章:

  • 郓城网站建设电话如何建立自己的商城
  • redis wordpress缓存郑州百度seo排名公司
  • 德清建设银行网站网站发送邮件功能
  • 班级网站建设html制作免费高清视频素材网站有哪些
  • 像京东一样的网站国外那些视频网站做的不错
  • 北京餐饮网络营销公司搜索引擎优化的基本原理
  • 网站建设图片设置优设网页
  • 以投资思维做网站广州公司网站设计制作
  • 怎么添加网站备案号德州网站怎样建设
  • 超值的扬中网站建设wordpress文章页seo设置
  • 新开的公司做网站多少钱工作压力大
  • 网站的管理有是WordPress小说网源码
  • 深圳做网站网络公司怎么样威联通wordpress怎么用
  • 提供网站建设方案装饰设计乙级资质承接范围
  • 域名解析后怎么做网站网站 备案网站
  • 网站内页可以做关键词优化吗制作影视视频的软件
  • 网站制作app开发公司qq是哪家公司开发的软件
  • 网站手机端 怎么做网站免费获取验证码怎么做
  • 网站内容创意c2c网站名称
  • 资源网站源码wordpress头像加V
  • 怎么搭建视频网站安居客看房网
  • 哈尔滨优化网站排名做网站开发的想接私活
  • 通江县城乡建设局门户网站河南企业做网站
  • 包头天亿网站建设公司如何建立一个网站平台
  • 国内商城网站建设大学生兼职网站策划书
  • php户外运动产品企业网站源码做网站分什么软件
  • 电子商务网站建设 试卷河南网站域名备案
  • 网站建设优化服务咨询浙江网络安全学院
  • 好玩的游戏平台网站如何优化
  • 网站二级目录怎么做wordpress rewrite插件