Использование команд FTP для загрузки файла с сокетами - PullRequest
2 голосов
/ 08 октября 2019

Я использую проприетарный язык программирования, и он не имеет встроенной функции FTP. Поэтому я использую sockets.

sHandle := SocketOpen('ftp.stackoverflow.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-Добро пожаловать в stackoverflow FTP
220Несанкционированный доступ запрещен!
331 Требуется пароль для пользователя1673665
230. Вход в систему
250 CWD успешен. «/ update» является текущим каталогом.

Но почему я получаю после retr update.txt эту ошибку:

503 Плохая последовательность команд.

Я отлаживаю код постепенно, шаг за шагом. Поэтому время отклика не должно быть проблемой.

Ответы [ 3 ]

3 голосов
/ 08 октября 2019

Команде RETR должно предшествовать, по крайней мере, PASV или PORT для настройки соединения для передачи данных.

Обратитесь к RFC 959 , в частности, к разделу «3.2. Установление соединений для передачи данных»


Также обратите внимание, что команды FTP должны отправляться в верхнем регистре.

2 голосов
/ 10 октября 2019

Спасибо Мартину Прикрилу и Штеффену Ульриху за вашу помощь. Я добавлю здесь рабочий код с комментариями. Может быть, это будет кому-то полезно. Возможно, необходимо добавить команды сна, потому что код работает быстрее, чем сервер отвечает.

# Open control channel
sHandle := SocketOpen('ftp.stackoverflow.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);
1 голос
/ 08 октября 2019

Почему retr update.txt не работает?

Поскольку вы не соблюдаете спецификацию протокола FTP. Передача данных осуществляется с использованием отдельного TCP-соединения, которое необходимо предварительно настроить с помощью команд PASV, EPSV, PORT или EPRT. Для получения дополнительной информации см. Стандарты (вот для чего они предназначены), например RFC 959 и RFC 2428 .

...