LuaSocket FTP总是超时

时间:2008-10-16 21:25:48

标签: ftp lua luasocket passive-mode

我在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

所以我尝试了针对这两个不同但同样失败的FTP站点的LuaSocket。我也从另一台主动FTP工作的机器上尝试过它,并且它没有任何更好的运气(大概是因为LuaSocket总是使用被动模式,从我通过阅读socket/ftp.lua中的来源可以看出来。) / p>

那么这里的任何人都可以在顶级工作中使用LuaSocket双线程吗?请注意,在我的计算机上,主动FTP到戴尔的站点不起作用(我可以连接,但一旦ls它断开连接),所以如果你让LuaSocket工作,请注意是否有活动的FTP到戴尔的网站从另一个程序在你的机器上工作。

3 个答案:

答案 0 :(得分:3)

嗯。看起来问题是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时代。)

答案 1 :(得分:1)

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

答案 2 :(得分:1)

这个问题现在已经解决了,问题和第一个答案都有很大的帮助。

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

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

解决方案是将更改密码更改为PASV,并且是针对命令区分大小写的服务器的变通方法。详细信息在Lua电子邮件列表中,存档将在几天内通过Web访问。

(编辑ftp.lua第59行)