使用 FTP 命令下载带套接字的文件
Using FTP commands to download a file with sockets
我使用的是专有编程语言,它没有内置 FTP
功能。因此我使用 sockets
.
sHandle := SocketOpen('ftp.Whosebug.net', 21);
SocketReadString(sHandle, answer);
retW := SocketWriteString(sHandle, 'user user1673665' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
retW := SocketWriteString(sHandle, 'pass !@#$%^&*' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
retW := SocketWriteString(sHandle, 'cwd update' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
retW := SocketWriteString(sHandle, 'retr update.txt' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
SocketClose(sHandle);
这些是我从 FTP
服务器收到的答案:
220-Welcome to Whosebug FTP
220 Unauthorized access is illegal!
331 Password required for user1673665
230 Logged on
250 CWD successful. "/update" is current directory.
但是为什么我在retr update.txt
之后得到这个错误:
503 Bad sequence of commands.
我正在逐步调试代码。因此响应时间应该不是问题。
RETR
命令之前必须至少有 PASV
或 PORT
才能设置数据连接。
请参阅 RFC 959,尤其是 “3.2. 建立数据连接”部分
使用 PASV
时,您必须打开服务器在 227
响应中返回的端口的连接。
另请注意,FTP 命令应以大写形式发送。
Why does retr update.txt
not work?
因为您没有遵循 FTP 协议的规范。数据传输使用单独的 TCP 连接完成,需要使用 PASV
、EPSV
、PORT
或 EPRT
命令预先设置。有关详细信息,请参阅标准(这就是它们的用途),即 RFC 959 and RFC 2428.
感谢 Martin Prikryl 和 Steffen Ullrich 的帮助。我将在此处添加带有注释的工作代码。也许它对某人有用。也许有必要添加睡眠命令,因为代码运行速度比服务器响应速度快。
# Open control channel
sHandle := SocketOpen('ftp.Whosebug.net', 21);
SocketReadString(sHandle, answer);
SocketWriteString(sHandle, 'USER user1673665' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
SocketWriteString(sHandle, 'PASS !@#$%^&*' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
SocketWriteString(sHandle, 'CWD update' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
# Enter passive mode and receive data channel adress and port
SocketWriteString(sHandle, 'PASV' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
# Create adress for data channel
IF answer <> NOVALUE THEN
# Split answer on character , and ( and ) and whitespace
retPASV[] := StrSplit(answer, ',() ');
ENDIF;
CASE retPASV[1]
# Passive mode is 227
IS = 227 DO
connect := retPASV[6] & '.' & retPASV[7] & '.' & retPASV[8] & '.' & retPASV[9];
IS DO
ENDCASE;
# Create port for data channel
# Port is secondlast number * 256 + last number from PASV reply
port := String2Num(retPASV[10]) * 256 + String2Num(retPASV[11]);
# Open data channel on sHandle2
sHandle2 := SocketOpen(connect, port);
SocketReadString(sHandle2, answer2);
# Download file on control channel
SocketWriteString(sHandle, 'RETR update.txt' & CHR(13) & CHR(10));
SocketReadString(sHandle, Antwort);
# Read file on data channel - result of textfile in string answer2
SocketReadString(sHandle2, answer2);
SocketClose(sHandle);
我使用的是专有编程语言,它没有内置 FTP
功能。因此我使用 sockets
.
sHandle := SocketOpen('ftp.Whosebug.net', 21);
SocketReadString(sHandle, answer);
retW := SocketWriteString(sHandle, 'user user1673665' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
retW := SocketWriteString(sHandle, 'pass !@#$%^&*' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
retW := SocketWriteString(sHandle, 'cwd update' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
retW := SocketWriteString(sHandle, 'retr update.txt' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
SocketClose(sHandle);
这些是我从 FTP
服务器收到的答案:
220-Welcome to Whosebug FTP
220 Unauthorized access is illegal!
331 Password required for user1673665
230 Logged on
250 CWD successful. "/update" is current directory.
但是为什么我在retr update.txt
之后得到这个错误:
503 Bad sequence of commands.
我正在逐步调试代码。因此响应时间应该不是问题。
RETR
命令之前必须至少有 PASV
或 PORT
才能设置数据连接。
请参阅 RFC 959,尤其是 “3.2. 建立数据连接”部分
使用 PASV
时,您必须打开服务器在 227
响应中返回的端口的连接。
另请注意,FTP 命令应以大写形式发送。
Why does
retr update.txt
not work?
因为您没有遵循 FTP 协议的规范。数据传输使用单独的 TCP 连接完成,需要使用 PASV
、EPSV
、PORT
或 EPRT
命令预先设置。有关详细信息,请参阅标准(这就是它们的用途),即 RFC 959 and RFC 2428.
感谢 Martin Prikryl 和 Steffen Ullrich 的帮助。我将在此处添加带有注释的工作代码。也许它对某人有用。也许有必要添加睡眠命令,因为代码运行速度比服务器响应速度快。
# Open control channel
sHandle := SocketOpen('ftp.Whosebug.net', 21);
SocketReadString(sHandle, answer);
SocketWriteString(sHandle, 'USER user1673665' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
SocketWriteString(sHandle, 'PASS !@#$%^&*' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
SocketWriteString(sHandle, 'CWD update' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
# Enter passive mode and receive data channel adress and port
SocketWriteString(sHandle, 'PASV' & CHR(13) & CHR(10));
SocketReadString(sHandle, answer);
# Create adress for data channel
IF answer <> NOVALUE THEN
# Split answer on character , and ( and ) and whitespace
retPASV[] := StrSplit(answer, ',() ');
ENDIF;
CASE retPASV[1]
# Passive mode is 227
IS = 227 DO
connect := retPASV[6] & '.' & retPASV[7] & '.' & retPASV[8] & '.' & retPASV[9];
IS DO
ENDCASE;
# Create port for data channel
# Port is secondlast number * 256 + last number from PASV reply
port := String2Num(retPASV[10]) * 256 + String2Num(retPASV[11]);
# Open data channel on sHandle2
sHandle2 := SocketOpen(connect, port);
SocketReadString(sHandle2, answer2);
# Download file on control channel
SocketWriteString(sHandle, 'RETR update.txt' & CHR(13) & CHR(10));
SocketReadString(sHandle, Antwort);
# Read file on data channel - result of textfile in string answer2
SocketReadString(sHandle2, answer2);
SocketClose(sHandle);