我正在 node.js 中编写一个 SFTP 服务器,但我在最后一个障碍中遇到了一个奇怪的问题,读取文件……这是一个非常晦涩的话题,但任何帮助将不胜感激。
在此处遵循版本 3 SFTP 规范:https ://filezilla-project.org/specs/draft-ietf-secsh-filexfer-02.txt
我一直在 OSX 上使用 FileZilla、Coda2 和命令行 sftp 测试服务器。在读取之前,每个函数在所有功能中都取得了成功,其中包括一些 64 位通信,但每个函数在读取文件时似乎都会产生不同的怪异行为。
根据规范(第 6.4 节),SSH_FXP_READ 应提供:
uint32 id <- request id
string handle <- file handle
uint64 offset
uint32 len
所有这些都带有有效的 id 和句柄,但偏移量和长度是另一回事。为简单起见,我在这里只使用 2 字节句柄。
Coda Expected:
5 ff 0 30000
6 ff 30000 30000
7 ff 60000 30000
8 ff 90000 30000
etc until EOF
Coda Real:
5 ff 0 30000
6 ff 30000 30000
7 ff 27232 30000
8 ff 89872 30000
9 ff 87104 30000
10 ff 149872 30000
Coda 获得了前两个权利,但随后失去了它......
现在我的第一个想法是我刚刚读错了 64 位偏移量:
(buf.readUInt32BE(0) << 32) + buf.readUInt32BE(4)
编辑:将位移示例从 8 更改为 32(仍然无法正常工作),还尝试了 node-bignum 和 node-int64,结果相同
这里 Javascript 的 53 位精度对于文件大小应该足够了吧?
所以我用 python unpack (">Q") 验证了读数并且是正确的。不仅如此,相同的 64 位处理程序还在 SSH_FXP_READDIR 和 SSH_FXP_STAT 中通信文件大小就好了..
所以让我们尝试不同的客户端,不会比这更糟吧?
FileZilla 实际上并不请求第一个块的长度,而是请求服务器在第一个块上返回的任何长度。不管返回数据的长度如何,偏移量似乎增加了 65536 字节或更多……</p>
我唯一能想到的是读取 64 位缓冲区是错误的,但即使手动读取它们也是错误的:
<Buffer 00 00 00 00 00 00 75 30> Expected:30000 Got:30000
<Buffer 00 00 00 00 00 00 6a 60> Expected:60000 Got:27232
我们甚至在它突破 32 位之前就遇到了错误。
现在,如果我完全忽略偏移量和长度,并在每次读取请求时将文件分块流式传输到客户端并在完成时提供 EOF 状态,它在所有客户端中都可以正常工作。但显然这无视规范,所以是个坏主意。
不幸的是,没有太多相关代码可以发布,因为这似乎是一个非常基本的问题。
任何想法或见解将不胜感激。在这一点上,我什至不在乎它是否是一个基本错误:)