LuaSocket FTP 总是超时

Posted

技术标签:

【中文标题】LuaSocket FTP 总是超时【英文标题】:LuaSocket FTP always times out 【发布时间】:2010-09-17 15:28:20 【问题描述】:

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

我认为可能是我需要 LuaSocket 才能使用被动 FTP,但后来我发现它似乎默认这样做。我试图通过 FTP 检索的文件可以通过我机器上的其他程序使用被动 FTP 访问,但不能通过主动模式访问。我发现some talk 关于“入侵”LuaSocket 的被动模式支持,并且该讨论意味着以后的版本停止使用被动模式,但我的版本似乎仍然使用被动模式(我使用的是 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 上的 strace 下运行它(与 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

所以我尝试了 LuaSocket 来对付这两个不同的 FTP 站点,但都失败了。我还在另一台可以使用主动 FTP 的机器上尝试了它,但它并没有更好的运气(大概是因为 LuaSocket 总是使用被动模式,从我可以通过阅读socket/ftp.lua 中的源代码得知)。

那么这里的任何人都可以让 LuaSocket 两线在顶部工作吗?请注意,在我的机器上,到戴尔站点的活动 FTP 不起作用(我可以连接,但一旦我这样做 ls 它就会断开连接),所以如果你让 LuaSocket 工作,请注意是否从另一个到戴尔站点的活动 FTP程序在您的机器上运行。

【问题讨论】:

【参考方案1】:

嗯。看起来问题在于 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"))

反常地,使用 getfenv、getmetatable 等进行的 navelnaut 探险似乎并不值得。我认为这是设计的一个严重问题。 (LuaSocket)

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

【讨论】:

这完全有效。除了您的列表,我还将“retr”更改为“RETR”,仅此而已。干得好。 我也把它发给了 LuaSocket 维护者。希望下一个版本能够修复。【参考方案2】:

请注意,服务器未能遵循 FTP 规范,该规范指出命令不区分大小写。请参阅 RFC959,第 5.3 节“命令代码是四个或更少的字母字符。 处理大小写字母字符 同样。因此,以下任何一项都可能代表 检索命令: RETR Retr retr ReTr rETr"

【讨论】:

【参考方案3】:

此问题现已修复,问题和第一个答案有很大帮助。

Luasocket 对 RFC 959 是正确的(这里的第一条评论是关于大写的,请参阅 RFC959 第 5.2 节)

至少 Microsoft FTP 服务器不兼容。可能还有其他人。

解决方案是将 pasv 更改为 PASV,这是命令区分大小写服务器的解决方法。详细信息在 Lua 电子邮件列表中,档案将在几天后通过网络访问。

(编辑 ftp.lua 的第 59 行)

【讨论】:

以上是关于LuaSocket FTP 总是超时的主要内容,如果未能解决你的问题,请参考以下文章

luaSocket HTTP 请求总是以重定向响应(301 或 302)

使用Lua的扩展库LuaSocket用例

FTP上传文件连接超时,本地无问题,服务器上面连接超时?

luasocks的安装以及注意事项

如何在ubuntu上面安装luasocket

java使用ftp上传文件