摘要

  • RFC 1179 以信息性文本记录既有的 LPD 打印服务器协议:daemon 在 TCP 515 端口接收面向指定队列的命令,其中包括启动等待作业打印的命令。
  • 在 Receive job 过程中,daemon 先确认文件子命令;客户端以零字节标记自己已传完声明长度的文件;daemon 之后还要给出第二次确认。这些事实说明受控的文件接收,并不说明一页已经打印。

一个“成功”掩盖了几次交接

从提交者的视角,一次打印似乎只需要按下一个按钮。可在网络另一端,它至少经过不同的手:客户端发出请求,daemon 接受或拒绝一个协议步骤,队列保留等待项,打印进程开始运行,控制文件决定怎样解释数据文件,输出设备才可能形成物理结果。每一步的观察者不同,能证明的事情也不同。

RFC 1179 于 1990 年 8 月发布,描述的是当时在 Internet 上广泛使用的既有打印服务器协议,不是 Internet 标准。它没有把“打印完成”写成一个无所不包的网络回执。它描述命令、文件格式和 daemon 的回复,留下了一个重要的现实边界:网络对话能证明自己处理到哪里,不能替设备和纸张宣布发生了什么。

LPD 使用 TCP,daemon 监听 515 端口。每一条 daemon 命令都建立新的连接;二进制命令码之后是 ASCII 的打印队列名,必要时再带其他操作数。RFC 明确要求把命令名理解为向 daemon 提出的指令。指令送达与指令所指的世界状态改变,原本就是两件事。

例如 Print any waiting jobs:它在打印进程尚未运行时启动该进程。它并没有报告某个具体作业被选中,没有报告控制文件可被解释,也没有报告设备有纸、页面已成形或有人取走了输出。把“请求开始打印”写成“已打印”,会让一个命令盗用其后多段流程的结论。

接收文件有两个确认点

客户端进入 Receive job 后,可发送接收控制文件和接收数据文件的子命令。每发出一个子命令,客户端必须等待 daemon 的确认。一个全零字节代表正面确认,其他位型代表否定确认。这是 daemon 对下一项接收步骤的回答,不是对整个打印作业的裁决。

文件本身又有一道明确边界。子命令携带字节数和文件名;客户端在同一 TCP 连接上写入所声明数量的字节。写完后,它再发送一个零字节,表示自己认为传输的文件已完成;此时必须发生第二级确认。具有指定长度的数据文件遵循同样的安排。

这三处事实不应混成一句“上传成功”。第一次确认关乎子命令;客户端的零字节是对声明字节序列完成的陈述;第二次确认是 daemon 在此边界之后的回应。第二次正面确认当然强于仅仅打开连接,但它的对象仍是这一次文件交换,而不是文件在打印链条末端产生的可见结果。

字节数也不解释文件。RFC 1179 允许数据文件携带任何八位值,并指出其内容的解释由相应控制文件决定。相同数量的字节并不证明其中是有效的打印描述,不证明 formatter 能理解它,更不证明设备已把它变成一页纸。

控制文件是指令,不是人物与结果的档案

控制文件可提供主机名、用户标识、源文件名、打印格式和打印后发邮件等信息。它们指导 daemon 如何处理数据,不是经核验的人物身份、文件所有权或通知已被接收的证明。作业号在 RFC 的有限模型中区分作业,并不因此获得全局、永久的身份意义。

队列管理同样有边界。LPD 可以返回短或长的队列状态,也可以接收带有队列、agent 和用户名或作业号列表的删除命令。RFC 对非 root agent 删除他人作业有所限制。这是本地命令的一项约束,而不是关于谁有权阅读、释放、拥有或获得文档的完整治理系统。

LPD 的历史价值,正在于让可以核验的中间状态有了名字。我们可以说 daemon 接受了子命令,客户端声明一串字节结束,daemon 在此后作出回应,系统收到启动等待队列的命令。要说某页已打印、被领取或造成了业务效果,则需要来自后续节点的独立观察。

来源