3

LuaSocketの TCP 機能には成功しましたが、その FTP モジュールに問題があります。(小さい) ファイルを取得しようとすると、常にタイムアウトが発生します。パッシブ モード (Ubuntu Dapper Linux) で Firefox または ftp を使用して、ファイルを問題なくダウンロードできます。

パッシブ FTP を使用するには LuaSocket が必要なのかもしれないと思ったのですが、デフォルトでそうしているように見えることがわかりました。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"))

これにより、タイムアウトが発生します。Linuxで実行しました ( Solarisstraceと同じ)。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

そのため、これら 2 つの異なる FTP サイトに対して LuaSocket を試してみましたが、異なるが同様の失敗がありました。アクティブな FTP が動作する別のマシンからも試してみましたが、うまくいきませんでした (おそらく、LuaSocket は常にパッシブ モードを使用しているためですsocket/ftp.lua

では、LuaSocket の 2 ライナーを一番上の作業にできる人はいますか? 私のマシンでは、Dell のサイトへのアクティブな FTP が機能しないことに注意してください (接続できますが、接続するとすぐlsに切断されます)。LuaSocket を機能させる場合は、別のプログラムから Dell のサイトへのアクティブな FTP が機能するかどうかにも注意してください。あなたのマシン。

4

3 に答える 3

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 などを使用した航海士の遠征は価値がないように思われました。設計上の深刻な問題だと思います。(LuaSocket の)

RFC0959ではすべて大文字のコマンドが使用されていることに注意してください。(おそらく7ビットASCII時代のものだからです。)

于 2008-10-18T02:54:52.493 に答える
1

この問題は修正され、質問と最初の回答が非常に役立ちます。

LuasocketはRFC959に正しいです(ここでの最初のコメントは大文字について正しくありません。RFC959セクション5.2を参照してください)

少なくともMicrosoftFTPサーバーは準拠していません。他にもあるかもしれません。

解決策は、pasvをPASVに変更することであり、コマンドの大文字と小文字を区別するサーバーの回避策です。詳細はLuaのメーリングリストにあり、アーカイブは数日以内にWebにアクセスできるようになります。

(ftp.luaの59行目を編集)

于 2008-11-07T21:19:06.007 に答える
1

サーバーは、コマンドが大文字と小文字を区別しないという FTP 仕様に準拠していないことに注意してください。RFC959 のセクション 5.3 を参照してください。「コマンド コードは 4 文字以下の英字です。大文字と小文字の英字は同じように扱われます。したがって、次のいずれかが取得コマンドを表す場合があります: RETR Retr retr ReTr rETr」

于 2008-11-07T16:38:05.730 に答える