У LuaSocket FTP всегда время ожидания - PullRequest
3 голосов
/ 17 октября 2008

У меня был успех с LuaSocket TCP, но у меня проблемы с его модулем FTP. Я всегда получаю тайм-аут при попытке получить (маленький) файл. Я могу нормально загрузить файл, используя Firefox или ftp в пассивном режиме (в Ubuntu Dapper Linux).

Я подумал, что, возможно, мне нужен LuaSocket для использования пассивного FTP, но потом я обнаружил, что, похоже, он делает это по умолчанию. Доступ к файлу, который я пытаюсь получить через FTP, можно получить с помощью пассивного FTP через другие программы на моем компьютере, но не через активный режим. Я обнаружил некоторые разговоры о "взломе" поддержки пассивного режима в 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"))

Это дает мне тайм-аут. Я запускал его под strace в Linux (так же, как ptrace в Solaris). Вот сокращенная стенограмма:

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 на сайт Dell не работает (я могу подключиться, но как только я ls отключается), поэтому, если вы заставляете LuaSocket работать, также обратите внимание, активен ли FTP на сайт Dell с другого Программа работает на вашем компьютере.

Ответы [ 3 ]

3 голосов
/ 18 октября 2008

Hm. Похоже, проблема в том, что LuaSocket использует «pasv» в нижнем регистре. Я собираюсь попытаться найти обходной путь.


Hm. Нет, это выглядит довольно элегантно заваренным. Легче всего сделать это, вероятно, скопировав этот конкретный файл в его эквивалентное место в иерархии по более раннему пути в 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 и т. Д., Похоже, не стоила того. Я считаю это серьезной проблемой с дизайном. (от LuaSocket)

Стоит отметить, что RFC0959 использует команды all-caps. (Возможно, потому что это из 7-битной эры ASCII.)

1 голос
/ 08 ноября 2008

Эта проблема теперь исправлена, с вопросом и первым ответом большая помощь.

Luasocket верен для RFC 959 (первый комментарий здесь не прав в отношении верхнего регистра, см. RFC959 раздел 5.2)

По крайней мере Microsoft FTP-сервер не совместим. Там могут быть другие.

Решение - изменить pasv на PASV и это обходной путь для сервера, чувствительного к командной строке. Подробности указаны в списке рассылки Lua, где архив будет доступен через несколько дней.

(редактировать строку 59 из ftp.lua)

1 голос
/ 07 ноября 2008

Обратите внимание, что сервер не соответствует спецификации FTP, в которой говорится, что команды не чувствительны к регистру. См. RFC959, раздел 5.3 «Коды команд состоят из четырех или менее буквенных символов. Буквы алфавита верхнего и нижнего регистра должны быть обработаны одинаково. Таким образом, любое из следующего может представлять получить команду: RETR Retr retr ReTr rETr "

...