摘要
- FTP 把一个文件动作分到两条连接上:数据连接搬运字节,控制连接保存命令状态。
1yz是肯定的预备回复,却明确表示动作尚未完成,之后还应有终局回复。 - 数据连接关闭没有唯一含义。正常文件结束、
ABOR、端口说明改变、控制连接关闭和不可恢复错误,都可能让数据通道消失。 - 活跃传输收到
ABOR时,426结束的是原传输,随后226完成的是中止命令。只保留最后一个正向代码,会把“成功取消”错写成“传输成功”。
三个看似结束的信号
设想接收端已经拿到预期字节数,文件名也出现在目录里,数据 TCP 连接以有序 FIN 关闭。对许多现代任务队列而言,这三个信号足以把状态改成绿色。
FTP 不允许它们单独作出这个决定。用户眼里的一次会话,在协议里至少有两条时间线。长期存在的控制连接承载命令和三位数字回复;临时数据连接承载目录清单、部分文件、整个文件或连续文件。数据进程能观察打开、字节、EOF 与运输故障,协议解释器才知道当前是哪条命令、是否只发过预备回复、最后应该由哪条回复收口。
这种分工不是 TCP 偶然留下的裂缝,而是 FTP 为异构主机作出的选择。控制对话可以继续,数据通道可以按动作生成和消失。代价是任何观测系统都必须承认:传输层的“已经结束”不自动继承应用层的“已经成功”。
1972 年的两个代码已经否定了“关闭即成功”
熟悉的回复类别尚未定型时,边界已经存在。1972 年 7 月的 RFC 354 列出 252 FTP transfer completed correctly,同时另列 452 FTP: File transfer incomplete, data connection closed。
两种结果都可能出现在数据连接关闭之后。区别不在套接字是否还活着,而在服务器如何报告文件动作。早期规范用两个句子留下了一个耐久的制度事实:运输结束只是证据,不能自行选择业务含义。
当时 FTP 还要跨越不同字长、字符表示、记录结构和存储系统。服务器协议解释器把命令与本地文件动作相连,数据传输进程负责线上表示。即使网络上的字节完整,转换、路径、写入和本地资源仍可能产生另一种结果。
但自由文本不利于程序。客户端需要从数字本身知道下一步:等待、继续、补充参数、稍后重试,还是把当前请求视为结束。
第一位数字变成状态规则
1974 年的 RFC 640 重整 FTP 回复。1yz 表示肯定的预备状态:动作已经启动,但尚未完成,还会有另一条回复。2yz 是肯定完成。3yz 接受此前命令,却等待更多信息。4yz 与 5yz 都是否定完成,只是重试含义不同。
因此,“肯定”从来不等于同一种成功。150 可以告诉客户端去关注数据连接,却不能授权它宣布文件动作已经完成。把所有首位不是 4 或 5 的代码装进一个 success 桶,会抹去协议最重要的状态差别。
RFC 640 还把预备回复提前到数据连接已经存在或即将尝试建立的时刻。这样无需等到连接完全建立才让客户端进入下一阶段,效率更高;相应地,证明范围也更窄。它证明服务器准备推进,不证明连接必然建立,更不证明传输结束。
125 或 150 之后仍欠一张收据
RFC 765 与 1985 年的 RFC 959 保留了这套两阶段结构。RFC 959 规定,一条命令至多得到一个 1yz;预备回复之后,服务器还必须发完成回复。
文件命令表把路径写得很清楚。125 表示数据连接已经打开并开始传输;150 表示文件状态正常,服务器将要打开数据连接。终局可能是表示成功的 226 或 250,也可能是 425、426、451、551、552 等适用失败。
所以,一份只有 150、完整字节数和数据 FIN 的抓取仍然缺少 FTP 层结果。反过来,终局失败也不会因为计数器恰好达到预期而消失。两套证据可以冲突,冲突本身正是需要保存的事实。
客户端通常在完成回复到来之前不发送下一条普通命令,也由此可以理解:前一个状态转换还没有释放。ABOR 和 STAT 之所以需要特殊处理,正因为它们必须在动作进行时抵达或询问解释器。
同一种关闭,至少五种原因
RFC 959 列出的服务器关闭数据连接原因包括:正常完成传输、收到中止请求、用户通过新命令改变端口说明、控制连接正常或异常关闭、发生不可恢复错误。
在 TCP 观测点上,这些事件可能都表现为连接结束;在 FTP 命令账上,它们完全不同。有序 FIN 只能说明运输交换怎样收尾,不能说明文件是否在预期边界结束、服务器是否确认了本地动作,也不能说明是不是主动服从了取消。
Stream 模式会以数据连接关闭表示文件结束。这是一条成帧规则,不是一份无限扩张的成功证明。FTP 对恢复的讨论正暴露其局限:如果只剩关闭事件,正常 EOF 与过早中断可能无法区分。
正确的监控模型至少保留两类事件:“观察到数据 EOF/关闭”与“FTP 命令以代码 X 完成”。二者即便发生在同一毫秒,也不能互相覆盖。
426 与 226 分别属于谁
ABOR 把动作归属问题放到最清楚的位置。如果此前服务已经完成,中止命令没有可停止的工作,服务器仍可用 226 报告 ABOR 已处理。这个 226 回答的是新命令,不是给旧文件动作补发担保。
如果传输仍在进行,RFC 959 要求两条回复。先用 426 表明数据连接关闭、原服务请求异常终止;再用 226 表明中止命令处理成功。
一段对话里因此有两个结果:
- 原传输 → 被中止,否定完成(
426); ABOR→ 执行成功,肯定完成(226)。
只存最后一条代码,会把取消的成功算给传输;把两条都绑定到原传输,又会误称中止失败。协议意义来自代码类别、顺序和所完成的动作,而不是来自最大、最后或看起来最乐观的数字。
226 的权限止于 FTP 边界
在普通完成路径上,226 表示数据连接正在关闭,所请求文件动作成功。它没有携带内容摘要,没有标识远端对象版本,也没有承诺字节已落入耐久介质、进入备份、继续保持权限、被下游程序消费或满足某项商业义务。
这些更强结论需要各自的收据:摘要证明内容相等,本地提交或同步记录说明持久化,不可变 ID 区分版本,应用回执说明后续接纳,业务系统判断义务是否履行。
缺少 226 也不等于远端没有副作用。服务器可能已经写完,却在回复抵达客户端之前失去控制连接。盲目重试可能重复或覆盖。此时应记录“FTP 结果未知”,而不是凭网络沉默宣布“未发生”。
FTP 的克制不偏向悲观或乐观。它只是把每一层允许说的话圈在边界内。
控制记录本来就是传输证据的一部分
可审计记录应包含命令及次序、125/150、所选数据端点、打开结果、字节与 EOF 观察、已知关闭原因、按顺序保存的所有终局回复,以及 ABOR/STAT 相对时刻。
还要并列保存 FTP 没有证明的事实:表示类型与传输模式、路径解析、本地文件动作、持久化结果、独立摘要和对象版本。并列不等于合并。
状态也不应只有 done。至少要区分:预备接受、等待数据连接、数据活动、数据已关而等待终局、传输肯定完成、传输否定完成、已请求中止、原传输已中止、中止已处理、控制结果未知。
一旦压成一个布尔值,之后不可能从“最后代码”还原哪项动作结束。不可逆损失发生在语义序列被删除时,而不是套接字关闭时。
来源与证据边界
本文依据 RFC 354、RFC 542、RFC 640、RFC 765、RFC 959 与 RFC 1123。它们确立两条连接、回复类别、关闭原因、文件动作序列与 ABOR 规则。
RFC 1123 在 1989 年称恢复、ABOR 与 Block 模式有助于稳健性,但当时并未广泛实现。这只是历史观察,不是当前产品普及率。上述材料也不能证明今天任何具体软件的行为、符合度或文件系统耐久性。
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
