LuaSocket FTP 经常超时。

我在LuaSocket 的 TCP 设施上取得了成功,但使用它的 FTP 模块时遇到了问题。我尝试重复下载一个(小)文件时总是会超时。在 Ubuntu Dapper Linux 上,我可以使用 Firefox 或在被动模式下使用 FTP 下载文件。

我以为可能需要让 LuaSocket 使用被动 FTP,但我发现它似乎已经默认使用被动 FTP。我尝试使用其他程序通过 FTP 的被动模式访问要重复下载的文件,但无法在主动模式下访问该文件。我找到了一些关于将被动模式支持“黑客”的讨论,并表明后来的版本停止使用被动模式,但我的版本似乎仍然使用被动模式(我使用 2.0.1;最新的版本是 2.0.2,似乎没有任何与我的用例相关的更改)。我对这篇文章与我的实际情况有些困惑,部分原因是它很旧,而且 LuaSocket 的源代码现在与该讨论中的代码基本上没有什么相似之处。

我将代码简化为:

local ftp = require "socket.ftp"
ftp.TIMEOUT = 10
print(ftp.get("ftp://ftp.us.dell.com/app/dpart.txt"))

这会让我超时。我在 Linux 上运行了它(与 Solaris 上的 ptrace 相同)。这是一个摘录的记录:

socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
fcntl64(3, F_SETFL, O_RDWR|O_NONBLOCK)  = 0
recv(3, "230-Welcome to the Dell FTP site."..., 8192, 0) = 971
send(3, "pasv\r\n", 6, 0)               = 6
recv(3, 0x8089a58, 8192, 0)             = -1 EAGAIN (Resource temporarily unavailable)
select(4, [3], NULL, NULL, {9, 999934}) = 0 (Timeout)

我尝试连接到另一个网站,但它有一个密码不能在这里发布,但在那种情况下结果略有不同……我得到了类似上面的跟踪,但 select() 最终成功,随后出现了这种情况:

recv(3, "227 Entering Passive Mode (123,456,789,0,12,34)\r\n", 8192, 0) = 49
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 4
fcntl64(4, F_SETFL, O_RDWR|O_NONBLOCK)  = 0
connect(4, {sa_family=AF_INET, sin_port=htons(12345), sin_addr=inet_addr("123.456.789.0")}, 16) = -1 EINPROGRESS (Operation now in progress)
select(5, [4], [4], NULL, {9, 999694})  = 0 (Timeout)

将其与我的“ftp”程序的被动模式跟踪进行比较(尽管请注意,它并没有像 LuaSocket 一样将套接字设置为非阻塞状态):

socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 6
write(5, "PASV\r\n", 6)                 = 6
read(3, "227 Entering Passive Mode (123,456,789,0,12,34)\r\n", 1024) = 51
connect(6, {sa_family=AF_INET, sin_port=htons(12345), sin_addr=inet_addr("123.456.789.0")}, 16) = 0

因此,我尝试了针对这两个不同的 FTP 站点使用 LuaSocket,但是失败情况略有不同但相似。我还在另一台可以使用主动 FTP 的机器上尝试了它,但是那里也无改善(可能是因为从我阅读 socket/ftp.lua 中的源代码,LuaSocket 始终使用被动模式)。

因此,这里有人能使顶部的 LuaSocket 两行代码正常工作吗?请注意,在我的机器上,使用主动 FTP 连接 Dell 的站点不起作用(我可以连接,但是一旦我执行 ls 它就会断开连接),因此,如果您让 LuaSocket 正常工作,请还注意其他程序是否可以从 Dell 的网站使用主动 FTP 在您的机器上工作。

原文链接 https://stackoverflow.com/questions/210371

点赞
stackoverflow用户1421
stackoverflow用户1421

嗯,看起来问题在于LuaSocket使用小写的“pasv”。我会尝试找出一种解决方法。


嗯,看起来它被完美地焊死了。最简单的方法可能是将_那个特定文件_复制到较早LUA_PATH路径中的等效位置中。也就是说,(通常)将文件本地复制一份,例如path/to/your/project/socket/ftp.lua

然后编辑本地文件:

-    self.try(self.tp:command("user", user or USER))
+    self.try(self.tp:command("USER", user or USER))
-        self.try(self.tp:command("pass", password or PASSWORD))
+        self.try(self.tp:command("PASS", password or PASSWORD))
-    self.try(self.tp:command("pasv"))
+    self.try(self.tp:command("PASV"))
-    self.try(self.tp:command("port", arg))
+    self.try(self.tp:command("PORT", arg))
-    local command = sendt.command or "stor"
+    local command = sendt.command or "STOR"
-    self.try(self.tp:command("cwd", dir))
+    self.try(self.tp:command("CWD", dir))
-    self.try(self.tp:command("type", type))
+    self.try(self.tp:command("TYPE", type))
-    self.try(self.tp:command("quit"))
+    self.try(self.tp:command("QUIT"))

恶意地,使用getfenvgetmetatable等方法的寻经探航似乎不值一试。我认为这是LuaSocket设计上的一个严重问题。

值得注意的是,RFC0959使用全大写命令。(可能是因为它来自于7位ASCII时代。)

2008-10-18 02:54:52
stackoverflow用户88888888
stackoverflow用户88888888

注意,该服务器不能遵循FTP规范,该规范规定命令不区分大小写。请参见RFC959,第5.3节“命令代码是四个或更少的字母字符。大小写字母字符应该被视为相同。因此,以下任何一种都可以表示检索命令:RETR Retr retr ReTr rETr”

2008-11-07 16:38:05
stackoverflow用户88888888
stackoverflow用户88888888

这个问题现在已经解决了,问题和第一个答案非常有帮助。

Luasocket符合RFC959(第一个评论不正确,有关大写字母,请参见RFC959第5.2节)

至少微软FTP服务器不符合规定。可能还有其他。

解决方案是将pasv更改为PASV,并且是对命令大小写敏感的服务器的解决方法。详细信息在Lua电子邮件列表上,其中档案将在几天内可在网站上访问。

(编辑ftp.lua的第59行)

2008-11-07 21:19:06