第 1 章 - Azure RTOS NetX FTP 简介

文件传输协议 (FTP) 是为文件传输而设计的协议。 FTP 利用可靠的传输控制协议 (TCP) 服务来实现文件传输功能。 因此,FTP 是一种高度可靠的文件传输协议。 FTP 也是高性能的。 实际的 FTP 文件传输是在专用的 FTP 连接上执行的。

FTP 要求

为了能够正常运行,Azure RTOS NetX FTP 包要求已经创建了 NetX IP 实例。 此外,必须在同一个 IP 实例上启用 TCP。 NetX FTP 包的 FTP 客户端部分没有进一步的要求。

NetX FTP 包的 FTP 服务器部分有几个额外的要求。 首先,它要求完全访问 TCP 已知端口 21 来处理所有客户端 FTP 命令请求,以及完全访问已知端口 20 来处理所有客户端 FTP 数据传输。 FTP 服务器还设计为与 FileX 嵌入式文件系统配合使用。 如果 FileX 不可用,用户可以将使用的 FileX 部分移植到他们自己的环境中。 本指南后面的几部分将对此进行讨论。

FTP 约束

关于文件数据的表示,FTP 标准提供了许多选择。 与 Unix 实现类似,NetX FTP 假设有以下文件格式约束:

  • 文件类型:二进制
  • 文件格式:仅非打印
  • 文件结构:仅文件结构
  • 传输模式:仅流模式

FTP 文件名

FTP 文件名应采用目标文件系统(通常是 FileX)的格式。 它们应为以 NULL 结尾的 ASCII 字符串,如果需要,还应该包含完整的路径信息。 在 NetX FTP 实现中,没有指定对 FTP 文件名大小的限制。 但是,数据包池有效负载大小应能够容纳最大路径和/或文件名。

FTP 客户端命令

FTP 有一种用于打开连接以及执行文件和目录操作的简单机制。 基本上有一组标准 FTP 命令,客户端会在已知 TCP 端口 21 上成功建立连接后发出这些命令。 下面展示了一些基本 FTP 命令:

FTP 命令和含义

  • CWD path:更改工作目录
  • DELE filename:删除指定的文件名
  • LIST directory:获取目录列表
  • MKD directory:生成新目录
  • NLST directory:获取目录列表
  • NOOP:无操作,返回成功
  • PASS password:提供登录密码
  • PASV:请求被动传输模式
  • PWD path:拾取当前目录路径
  • QUIT:终止客户端连接
  • RETR filename:读取指定文件
  • RMD directory:删除指定目录
  • RNFR oldfilename:指定要重命名的文件
  • RNTO newfilename:将文件重命名为所提供的文件名
  • STOR filename:写入指定文件
  • TYPE I:选择二进制文件图像
  • USER username:提供登录用户名
  • PORT ip_address,port:提供 IP 地址和客户端数据端口

这些 ASCII 命令是 NetX FTP 客户端软件内部使用的,用于与 FTP 服务器进行 FTP 操作。

FTP 服务器响应

FTP 服务器利用已知 TCP 端口 21 来处理客户端命令请求。 在处理客户端命令后,FTP 服务器就会返回 3 位数的 ASCII 数字响应,后跟一个可选的 ASCII 字符串。 FTP 客户端软件使用此数字响应来确定操作是成功还是失败。 下面列出了 FTP 服务器对客户端命令的各种响应:

第一个数字字段和含义

  • 1xx:积极的初步状态 – 即将返回另一个答复。
  • 2xx:积极的完成状态。
  • 3xx:积极的初步状态 – 必须发送另一个命令。
  • 4xx:临时错误状态。
  • 5xx:错误状态。

第二个数字字段和含义

  • x0x:命令中出现语法错误。
  • x1x:信息性消息。
  • x2x:与连接相关。
  • x3x:与身份验证相关。
  • x4x:未指定。
  • x5x:与文件系统相关。

例如,如果断开连接成功,那么使用 QUIT 命令断开 FTP 连接的客户端请求通常会收到来自服务器的“221”响应代码。

FTP 被动传输模式

默认情况下,NetX FTP 客户端使用主动传输模式通过数据套接字与 FTP 服务器交换数据。 这种安排的问题是,它要求 FTP 客户端打开 TCP 服务器套接字,以便 FTP 服务器连接。 这样做可能会带来安全风险,并可能会被客户端防火墙阻止。 被动传输模式与主动传输模式的不同之处在于,它是由 FTP 服务器在数据连接上创建 TCP 服务器套接字。 这消除了安全风险(对于 FTP 客户端)。

为了启用被动数据传输,应用程序在之前创建的 FTP 客户端上调用 nx_ftp_client_passive_mode_set(其中第二个参数设置为 NX_TRUE)。 此后,所有后续用于传输数据的 NetX FTP 客户端服务(NLST、RETR、STOR)都将尝试采用被动传输模式。

首先,FTP 客户端发送 PASV 命令(无参数)。 如果 FTP 服务器支持此请求,它就会返回 227“OK”响应。 然后,客户端发送请求(例如 RETR)。 如果服务器拒绝被动传输模式,则 NetX FTP 客户端服务就会返回错误状态。

为了禁用被动传输模式并恢复主动传输模式,应用程序调用 nx_ftp_client_passive_mode_set(其中第二个参数设置为 NX_FALSE)。

FTP 通信

FTP 服务器利用已知 TCP 端口 21 来处理客户端请求。 FTP 客户端可以使用任何可用的 TCP 端口。 FTP 事件的一般顺序如下:

FTP 读取文件请求

  1. 客户端发起与服务器端口 21 进行 TCP 连接。
  2. 服务器发送“220”响应来指明成功。
  3. 客户端发送带有“username”的“USER”消息。
  4. 服务器发送“331”响应来指明成功。
  5. 客户端发送带有“password”的“PASS”消息。
  6. 服务器发送“230”响应来指明成功。
  7. 客户端发送“TYPE I”消息进行二进制传输。
  8. 服务器发送“200”响应来指明成功。
  9. 客户端发送带有 IP 地址和端口的“PORT”消息。
  10. 服务器发送“200”响应来指明成功。
  11. 客户端发送带有要读取的文件名的“RETR”消息。
  12. 服务器创建数据套接字,并连接到“PORT”命令中指定的客户端数据端口。
  13. 服务器发送“125”响应来指明已开始读取文件。
  14. 服务器通过数据连接发送文件内容。 此过程一直继续到文件完全传输完毕。
  15. 完成后,服务器断开数据连接。
  16. 服务器发送“250”响应来指明已成功读取文件。
  17. 客户端发送“QUIT”来终止 FTP 连接。
  18. 服务器发送“221”响应来指明已成功断开连接。
  19. 服务器断开 FTP 连接。

如前所述,通过 IPv4 和 IPv6 运行 FTP 的唯一区别是,对于 IPv6,PORT 命令被替换为 EPRT 命令

如果 FTP 客户端使用被动传输模式发出读取请求,则命令顺序如下所示(以粗体显示的行表示与主动传输模式不同的步骤):

  1. 客户端发起与服务器端口 21 进行 TCP 连接。
  2. 服务器发送“220”响应来指明成功。
  3. 客户端发送带有“username”的“USER”消息。
  4. 服务器发送“331”响应来指明成功。
  5. 客户端发送带有“password”的“PASS”消息。
  6. 服务器发送“230”响应来指明成功。
  7. 客户端发送“TYPE I”消息进行二进制传输。
  8. 服务器发送“200”响应来指明成功。
  9. 客户端发送“PASV”消息。
  10. 服务器发送“227”响应以及客户端要连接到的 IP 地址和端口来指明成功。
  11. 客户端发送带有要读取的文件名的“RETR”消息。
  12. 服务器创建数据服务器套接字,并侦听此套接字上使用“227”响应中指定端口的客户端连接请求。
  13. 服务器在控制套接字上发送“150”响应来指明已开始读取文件。
  14. 服务器通过数据连接发送文件内容。 此过程一直继续到文件完全传输完毕。
  15. 完成后,服务器断开数据连接。
  16. 服务器在控制套接字上发送“226”响应来指明已成功读取文件。
  17. 客户端发送“QUIT”来终止 FTP 连接。
  18. 服务器发送“221”响应来指明已成功断开连接。
  19. 服务器断开 FTP 连接。

FTP 写入请求

  1. 客户端发起与服务器端口 21 进行 TCP 连接。
  2. 服务器发送“220”响应来指明成功。
  3. 客户端发送带有“username”的“USER”消息。
  4. 服务器发送“331”响应来指明成功。
  5. 客户端发送带有“password”的“PASS”消息。
  6. 服务器发送“230”响应来指明成功。
  7. 客户端发送“TYPE I”消息进行二进制传输。
  8. 服务器发送“200”响应来指明成功。
  9. 客户端发送带有 IP 地址和端口的“PORT”消息。
  10. 服务器发送“200”响应来指明成功。
  11. 客户端发送带有要写入的文件名的“STOR”消息。
  12. 服务器创建数据套接字,并连接到“PORT”命令中指定的客户端数据端口。
  13. 服务器发送“125”响应来指明已开始写入文件。
  14. 客户端通过数据连接发送文件内容。 此过程一直继续到文件完全传输完毕。
  15. 完成后,客户端断开数据连接。
  16. 服务器发送“250”响应来指明已成功写入文件。
  17. 客户端发送“QUIT”来终止 FTP 连接。
  18. 服务器发送“221”响应来指明已成功断开连接。
  19. 服务器断开 FTP 连接。

如果 FTP 客户端使用被动传输模式发出写入请求,则命令顺序如下所示(以粗体显示的行表示与主动传输模式不同的步骤):

  1. 客户端发起与服务器端口 21 进行 TCP 连接。
  2. 服务器发送“220”响应来指明成功。
  3. 客户端发送带有“username”的“USER”消息。
  4. 服务器发送“331”响应来指明成功。
  5. 客户端发送带有“password”的“PASS”消息。
  6. 服务器发送“230”响应来指明成功。
  7. 客户端发送“TYPE I”消息进行二进制传输。
  8. 服务器发送“200”响应来指明成功。
  9. 客户端发送“PASV”消息。
  10. 服务器发送“227”响应以及客户端要连接到的 IP 地址和端口来指明成功。
  11. 客户端发送带有要写入的文件名的“STOR”消息。
  12. 服务器创建数据服务器套接字,并侦听此套接字上使用“227”响应中指定端口的客户端连接请求。
  13. 服务器在控制套接字上发送“150”响应来指明已开始写入文件。
  14. 客户端通过数据连接发送文件内容。 此过程一直继续到文件完全传输完毕。
  15. 完成后,客户端断开数据连接。
  16. 服务器在控制套接字上发送“226”响应来指明已成功写入文件。
  17. 客户端发送“QUIT”来终止 FTP 连接。
  18. 服务器发送“221”响应来指明已成功断开连接。
  19. 服务器断开 FTP 连接。

FTP 身份验证

每当进行 FTP 连接时,客户端都必须为服务器提供“username”和“password”。 一些 FTP 站点允许所谓的“匿名 FTP”,即允许在没有特定用户名和密码的情况下进行 FTP 访问。 对于这种类型的连接,应提供“匿名”用户名,密码应为完整的电子邮件地址。

用户负责向 NetX FTP 提供登录和注销身份验证例程。 这些是在 nx_ftp_server_create 函数期间提供的,并通过密码处理来调用。 如果 login 函数返回 NX_SUCCESS,则表示连接已经过身份验证,允许执行 FTP 操作。 否则,如果 login 函数返回的不是 NX_SUCCESS,则连接尝试会被拒绝。

FTP 多线程支持

可以从多个线程同时调用 NetX FTP 客户端服务。 但是,对于特定 FTP 客户端实例的读取或写入请求应通过同一个线程依次执行。

FTP RFC

NetX FTP 符合 RFC959 和相关 RFC。