Опыт применения REXX FTP API

Автор: VicTor Smirnoff

Дата: апрель 2010

Источник: https://www.halfos.ru/

Данную книгу можно рассматривать как дополнение к переводу книги "Open Object REXX: Библиотека классов RxFtp. Справочник" и она является более ранним материалом, посвящённый исключительно полуосевой библиотеке функций RxFTP.

 «В отличие от ooRexx, где лицензионные ограничения не помешали мне выполнить прямой перевод документации, здесь представлены результаты некоторого исследования поведения функций OS/2 REXX FTP API, что, конечно же, потребовало включения в материал и полного описания всех функций :)», говорит VicTor Smirnoff о своей книге.

Прочитать книгу в интернете, можно на сайте автора по этой ссылке.

Скачать книгу в формате doc, можно по этой ссылке.

 

Оглавление:

  1.  Опыт применения REXX FTP API 
  2. Введение
  3. Установка
  4. Коды возврата
  5. Функции
  6. Замечания по применению
  7. Послесловие

1. Предисловие.

Данная работа посвящена практическим особенностям использования REXX FTP API и основана на опыте, имеющемся у автора.

В ней подробно разобрана работа каждой функции библиотеки, реализующей REXX FTP API, описаны особенности и даны рекомендации для практического применения.

В качестве примеров приведены тексты законченных работоспособных программ. Работоспособность программ проверена на библиотеке rxFtp версии 2.1.

Если оригинальная документация противоречила практике применения, то такие случаи отмечены особо. Также отмечены ошибки и неточности, встреченные в оригинальной документации.

Сообщения об обнаруженных ошибках и неточностях будут с благодарностью приняты автором.

2. Введение.

Функции REXX FTP API обеспечивают доступ к FTP из программ на языке REXX, используя OS/2 FTP API. Поскольку названия функций REXX FTP API созвучны подкомандам FTP, то читателю, знакомому с основами FTP, не составит труда ориентироваться в них.

Примечание:

Описание подкоманд FTP можно найти в Руководстве по TCP/IP (TCP/IP Guide).

Описание функций FTP API можно найти в Описании команд TCP/IP (TCP/IP Command Reference).

3. Установка.

Работу REXX FTP API обеспечивает файл RXFTP.DLL. Этот модуль DLL должен быть размещён в одном из каталогов, перечисленных в операторе LIBPATH файла CONFIG.SYS.

Чтобы получить возможность использовать в программе функции REXX FTP API, необходимо включить в неё следующие инструкции:
 

  rc = RxFuncAdd('FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs')
  rc = FtpLoadFuncs( )

Чтобы выгрузить DLL, сначала надо выполнить вызов функции:
 

  rc = FtpDropFuncs( )

Затем закрыть все сессии (CMD.EXE), в которых выполнялись программы REXX, использующие REXX FTP API. Библиотека будет освобождена системой и её можно будет удалить или заменить.

Примечание:

В некоторых случаях при возникновении ошибок библиотека может самостоятельно выводить на консоль диагностические сообщения. Например, возникновениеошибки FTPABORTможетсопровождатьсясообщением:
   abort: The file or directory specified cannot be found.

Файл сообщений об ошибках DDE4.MSG должен находиться в одном из каталогов, перечисленных в переменной окружения DPATH, задаваемой в файле CONFIG.SYS.

 

4. Коды возврата.

Функции REXX FTP API сообщают вызывающей программе об успешном или неуспешном выполнении с помощью кодов возврата и специальной переменной FTPERRNO.

Но делают это совершенно разными способами:

  1. Большинство функций возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

  1. Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

  1. Функция FtpSys() возвращает одно из следующих значений:

Значение

Описание

<строка>

нормальное завершение, ошибок нет;
строка содержит описание операционной системы сервера FTP;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

  1. Коды ошибок специальной переменной FTPERRNO смотри выше.
  2. Функция FtpVersion() всегда возвращает пустую строку ("").

    Cпециальной переменной FTPERRNO всегда присваивается значение 0.
  3. Функции FtpSetActiveMode(), FtpSetBinary() и FtpSetUser() возвращают одно из следующих значений:

Значение

Описание

1

нормальное завершение, ошибок нет

0

ошибка, требуемое действие не выполнено

  1. Cпециальной переменной FTPERRNO всегда присваивается значение 0.
  2. Функция FtpPing() возвращает одно из следующих значений:

Значение

Описание

<число>

нормальное завершение, ошибок нет;
время в миллисекундах, прошедшее от отправки запроса до получения ответа

PINGREPLY

хост не отвечает

PINGSOCKET

невозможно получить сокет

PINGPROTO

неизвестный протокол ICMP

PINGSEND

передача завершилась с ошибкой

PINGRECV

приём завершился с ошибкой

PINGHOST

неизвестный хост


  1. Cпециальной переменной FTPERRNO всегда присваивается значение 0.
  2. Функции FtpLoadFuncs() и FtpDropFuncs() возвращают 0 в случае успешного выполнения.

    Значение специальной переменной FTPERRNO не изменяется.

5. Функции.

Названия большинства функций REXX FTP API созвучны соответствующим подкомандам FTP. Поэтому в них легко ориентироваться тем, кто знаком с основами FTP.

5.1. FtpAppend().

Копирует файл с вашей рабочей станции на сервер FTP, добавляя его в конец существующего на сервере файла.

Синтаксис:

rc = FtpAppend( localFile, remoteFile [, pMode] )

Параметры:

localFile

имя файла на локальной рабочей станции

remoteFile

имя файла на сервере FTP

pMode

(необязательный) строка, определяющая режим передачи файлов:

'Ascii'

текстовый

'Binary'

двоичный

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpAppend() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем, в зависимости от выбранного режима FTP (активный или пассивный), отправляет на сервер одну из следующих последовательностей команд:

   TYPE        I=Binary, A=Ascii
   PORT <данные>    активный режим (по умолчанию)
   APPE <содержимое параметра remoteFile>
или
   TYPE        I=Binary, A=Ascii
   PASV             пассивный режим
   APPE <содержимое параметра remoteFile>

Если выполнение прошло успешно, то файл на сервере дописывается данными из локального файла.

Режим FTP нужно переключить заранее функцией FtpSetActiveMode() (по умолчанию, активный).

Если параметр pMode опущен, то выбирается режим передачи файлов ранее установленный функцией FtpSetBinary() (по умолчанию, двоичный).

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя локального файла, имя или адрес хоста и имя файла на сервере. А затем копирует локальный файл на сервер, добавляя его в конец существующего на сервере файла.

   /* rxFtpAppend.cmd - function example */
   parse arg fromFile pHost '/' toFile

   toFile = '/'||Strip( toFile );

   if pHost = '' | toFile = '/' then do
      say ''
      say 'Usage: rxFtpAppend localfile host/remotefile'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( 0 )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpAppend( fromFile, toFile, 'Binary' )
   if rc = -1 then do
      say ''
      say 'FtpAppend()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say 'File '||fromFile||' appended to '||toFile||' OK'
   end

   rc = FtpLogoff()
   /* end of file rxFtpAppend.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpAppend xxx.txt 127.0.0.1/Data/Ftp/Test.txt

   File xxx.txt appended to /Data/Ftp/Test.txt OK

   X:>rxFtpAppend C:\readme.txt 127.0.0.1/Data/Ftp/Test.txt

   File C:\readme.txt appended to /Data/Ftp/Test.txt OK

Связанныефункции:


FtpDelete(), FtpGet(), FtpLogoff(), FtpPut(), FtpPutUnique(), FtpRename(), FtpSetActiveMode(), FtpSetBinary(), FtpSetUser()

5.2. FtpChDir().

Переходит в указанный каталог на сервере FTP и делает его текущим.

Синтаксис:

rc = FtpChDir( remoteDir )

Параметры:

remoteDir

имя каталога на сервере FTP

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpChDir() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем отправляет на сервер следующую последовательность команд:

   CWD <содержимое параметра remoteDir>

Если выполнение прошло успешно, то текущим становится заданный каталог.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и имя каталога на сервере. А затем переходит в указанный каталог, делая его текущим на сервере.

   /* rxFtpChDir.cmd - function example */
   parse arg pHost '/' pDir

   pDir = '/'||Strip( pDir );

   if pHost = '' then do
      say ''
      say 'Usage: rxFtpChDir host[/dir]'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   if pDir \= '/' then do
      rc = FtpChDir( pDir )
      if rc = -1 then do
         say ''
         say 'FtpChDir()   FTPERRNO='||FTPERRNO
         signal halt
      end
   end

   rc = FtpPwd( xPwd )
   if rc = -1 then do
      say ''
      say 'FtpPwd()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say xPwd
   end

   halt:
   rc = FtpLogoff()
   /* end of file rxFtpChDir.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpChDir 127.0.0.1/Data/Ftp/Public

   "E:/data/ftp/public" is current directory.

   X:>rxFtpChDir ftp.software.ibm.com/pub

   "/pub" is current directory.

Связанныефункции:


FtpLogoff(), FtpMkDir(), FtpPwd(), FtpRmDir(), FtpSetUser()

5.3. FtpDelete().

Удаляет файл на сервере FTP.

Синтаксис:

rc = FtpDelete( remoteFile )

Параметры:

remoteFile

имя файла на сервере FTP

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpDelete() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем отправляет на сервер следующую последовательность команд:

   DELE <содержимое параметра remoteFile>

Если выполнение прошло успешно, то файл на сервере удаляется.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и имя файла на сервере. Азатемудаляетуказанныйфайлнасервере.

   /* rxFtpDelete.cmd - function example */
   parse arg pHost '/' pFile

   pFile = '/'||Strip( pFile );

   if pHost = '' | pFile = '/' then do
      say ''
      say 'Usage: rxFtpDelete host/file'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpDelete( pFile )
   if rc = -1 then do
      say ''
      say 'FtpDelete()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say 'File '||pFile||' deleted OK'
   end

   rc = FtpLogoff()
   /* end of file rxFtpDelete.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpDelete 127.0.0.1/Data/Ftp/Test.txt

   File /Data/Ftp/Test.txt deleted OK

Связанные функции:

FtpAppend(), FtpGet(), FtpLogoff(), FtpPut(), FtpPutUnique(), FtpRename(), FtpSetUser()

5.4. FtpDir().

Получает список содержимого каталога сервера FTP в развернутом виде.

Синтаксис:

rc = FtpDir( pPattern, pStem )

Параметры:

pPattern

шаблон выборки содержимого каталога.
Может содержать имя файла, имя каталога или шаблон имени файла с использованием символов-заменителей '*' и '?'.

Назначение символов-заменителей стандартно:

'?'

заменяет один любой символ в имени

'*'

заменяет любое количество символов в имени


Если в шаблоне не указан путь, то он применяется к содержимому текущего каталога.

pStem

строка, определяющая имя-основу набора переменных, в который будут помещены результаты;
строка обязательно должна заканчиваться точкой ('.').

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpDir() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем, в зависимости от выбранного режима FTP (активный или пассивный), отправляет на сервер одну из следующих последовательностей команд:

   PORT <данные>    активный режим (по умолчанию)
   LIST <содержимое параметра pPattern>
или
   PASV             пассивный режим
   LIST <содержимое параметра pPattern>

Если выполнение прошло успешно, то результатами заполняется набор переменных, имя-основа которых задаётся параметром pStem. Количество записей заносится в переменную из этого набора с индексом 0.

Например, пусть параметр pStem содержит строку 'files.'. Тогда в переменную files.0 будет помещено количество записей в списке, а сами записи будут последовательно помещены в переменные files.1, files.2 и т.д.

Режим FTP нужно переключить заранее функцией FtpSetActiveMode() (по умолчанию, активный).

Примечание:

Строка, передаваемая в параметре pPattern, может содержать имя файла, имя каталога или шаблон имени файла с символами-заменителями '*' и '?'.

Казалось бы, указав в качестве шаблона строку '*', можно получить полный список содержимого текущего каталога.

Однако серверы FTP неоднозначно обрабатывают такой запрос. Некоторые выдают ожидаемый список содержимого текущего каталога. Другие выдают список, в котором отсутствуют имена подкаталогов. Третьи же, выдав список файлов текущего каталога, заодно выдают и списки содержимого подкаталогов текущего каталога.

Поэтому для получения списка содержимого текущего каталога лучше использовать строку '.' (т.е. имя текущего каталога) в качестве параметра.

Такой запрос все серверы FTP обрабатывают однозначно.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и имя каталога на сервере. А затем отображает содержимое указанного каталога.

   /* rxFtpDir.cmd - function example */
   parse arg pHost '/' pDir

   pDir = '/'||Strip( pDir );

   if pHost = '' then do
      say ''
      say 'Usage: rxFtpDir host[/dir]'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   if pDir \= '/' then do
      rc = FtpChDir( pDir )
      if rc = -1 then do
         say ''
         say 'FtpChDir()   FTPERRNO='||FTPERRNO
         signal halt
      end
   end

   rc = FtpDir( '.', 'xFile.' )
   if rc = -1 then do
      say ''
      say 'FtpDir()   FTPERRNO='||FTPERRNO
   end
   else do
      if xFile.0 > 0 then do
         say ''
         do i = 1 to xFile.0
            say xFile.i
         end
      end
   end

   halt:
   rc = FtpLogoff()
   /* end of file rxFtpDir.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpDir 127.0.0.1

   351      A          04-11-10   11:10  error.log
     0      A    DIR   04-12-10   08:59  Misc Tools
     0           DIR   04-10-10   08:33  Public
    50                 04-10-10   08:34  ReadMe.txt
    10      A          04-10-10   13:57  Test.txt

   X:>rxFtpDir ftp.software.ibm.com/pub

   total 520
   -rw-r--r--   1 102004493 201  192970 Jan 28 2001  00_Catalog
   -rw-r--r--   1 102004493 201     802 Jan 14 1999  00_index
   -rw-r--r--   1 102004493 201     595 Jan 14 1999  00_index.tab
   -rw-r--r--   1 102004493 201    2095 Jan 17 1999  User_Documentation
   -rw-r--r--   1 102004493 201    5890 Jan 19 1999  User_Documentation.990517.rsr
   dr-xr-x--x   2 102004493 201     256 Aug  4 2008  bin
   drwxrwxr-x   4 102004493 201     256 Jan  1 1980  comm
   drwxrwxr-x  13 102004493 201    4096 Feb  9 08:02 demos
   <...
пропуск
...>

Связанныефункции:

FtpLogoff(), FtpLs(), FtpSetActiveMode(), FtpSetUser()

5.5. FtpDropFuncs().

Сбрасывает регистрацию всех функций REXX FTP API и делает их недоступными для использования.

Синтаксис:

rc = FtpDropFuncs( )

Параметры:

Параметров нет.

Возвращаемое значение:

Функции FtpLoadFuncs() и FtpDropFuncs() возвращают 0 в случае успешного выполнения.

Значение специальной переменной FTPERRNO не изменяется.

Описание:

Сбрасывает регистрацию и делает недоступными для использования все функции REXX FTP API.

Затем, чтобы выгрузить DLL, обеспечивающий работу REXX FTP API, необходимо закрыть все сессии (CMD.EXE), в которых выполнялись программы REXX, использующие REXX FTP API. Библиотека будет освобождена системой и её можно будет удалить или заменить.

Пример:

Чтобы получить возможность выгрузить DLL, обеспечивающий работу REXX FTP API, необходимо включить в программу следующую инструкцию:

   rc = FtpDropFuncs()

Связанные функции:

FtpLoadFuncs()

 

5.6. FtpGet().

Копирует одиночный файл с сервера FTP на рабочую станцию в указанный локальный файл.

Синтаксис:

rc = FtpGet( localFile, remoteFile [, pMode] )

Параметры:

localFile

имя файла на локальной рабочей станции

remoteFile

имя файла на сервере FTP

pMode

(необязательный) строка, определяющая режим передачи файлов:

'Ascii'

текстовый

'Binary'

двоичный

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpGet() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем, в зависимости от выбранного режима FTP (активный или пассивный), отправляет на сервер одну из следующих последовательностей команд:

   TYPE        I=Binary, A=Ascii
   PORT <данные>    активный режим (по умолчанию)
   RETR <содержимое параметра remoteFile>
или
   TYPE        I=Binary, A=Ascii
   PASV             пассивный режим
   RETR <содержимое параметра remoteFile>

Если выполнение прошло успешно, то локальный файл переписывается данными из файла, полученного с сервера.

Режим FTP нужно переключить заранее функцией FtpSetActiveMode() (по умолчанию, активный).

Если параметр pMode опущен, то выбирается режим передачи файлов ранее установленный функцией FtpSetBinary() (по умолчанию, двоичный).

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя локального файла, имя или адрес хоста и имя файла на сервере. А затем копирует файл с сервера на рабочую станцию в файл с указанным именем.

   /* rxFtpGet.cmd - function example */
   parse arg toFile pHost '/' fromFile

   fromFile = '/'||Strip( fromFile );

   if pHost = '' | toFile = '/' then do
      say ''
      say 'Usage: rxFtpGet localfile host/remotefile'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpGet( toFile, fromFile, 'Binary' )
   if rc = -1 then do
      say ''
      say 'FtpGet()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say 'File '||fromFile||' received to '||toFile||' OK'
   end

   rc = FtpLogoff()
   /* end of file rxFtpGet.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpGet xxx.txt 127.0.0.1/Data/Ftp/Test.txt

   File /Data/Ftp/Test.txt received to xxx.txt OK

   X:>rxFtpGet C:\robots.txt ftp.software.ibm.com/robots.txt

   File /robots.txt received to C:\robots.txt OK

Связанныефункции:

FtpAppend(), FtpDelete(), FtpLogoff(), FtpPut(), FtpPutUnique(), FtpRename(), FtpSetActiveMode(), FtpSetBinary(), FtpSetUser()

5.7. FtpLoadFuncs().

Регистрирует и делает доступными для использования все функции REXX FTP API.

Синтаксис:

rc = FtpLoadFuncs( [pMute] )

Параметры:

pMute

(необязательный) любое значение.

Если параметр задан, то подавляется вывод на консоль информации о библиотеке REXX FTP API.

Возвращаемое значение:

Функции FtpLoadFuncs() и FtpDropFuncs() возвращают 0 в случае успешного выполнения.

Значение специальной переменной FTPERRNO не изменяется.

Описание:

Регистрирует и делает доступными для использования все функции REXX FTP API.

Пример:

Чтобы получить возможность использовать в программе функции REXX FTP API, необходимо включить в неё следующие инструкции:

   rc = RxFuncAdd('FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs')
   rc = FtpLoadFuncs()

Пример вывода на консоль информации о библиотеке REXX FTP API:

   RxFtp 2.1 - REXX function package for tcp/ip ftp
   (c) Copyright International Business Machines Corporation 1993, 1999.
   All Rights Reserved.

Связанныефункции:


FtpDropFuncs()

5.8. FtpLogoff().

Завершаетсессию FTP.

Синтаксис:

rc = FtpLogoff( )

Параметры:

Параметров нет.

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpLogoff() проверяет наличие соединения с сервером FTP.

И, если соединение с сервером FTP существует, то отправляет на сервер следующую последовательность команд:

   QUIT

и закрывает соединение с сервером FTP.

Затем сбрасывает установки, сделанные функциями FtpSetBinary(), FtpSetActiveMode() и FtpSetUser(). Сессия FTP закрыта.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста. Затем отправляет на сервер неполную команду, после чего сервер по тайм-ауту разрывает соединение. Соединение автоматически восстанавливается во время следующей попытки доступа к серверу. Затемсессиязакрываетсяиработастановитсяневозможна.

   /* rxFtpLogoff.cmd - function example */
   parse arg pHost

   if pHost = '' then do
      say ''
      say 'Usage: rxFtpLogoff host'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpQuote( 'TYPE', xAnswer )
   if rc = -1 then do
      say ''
      say 'FtpQuote()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say xAnswer
   end

   rc = FtpSys( pSys )
   if rc = -1 then do
      say ''
      say 'FtpSys()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say pSys
   end

   rc = FtpLogoff()

   if rc = -1 then do
      say ''
      say 'FtpLogoff()   FTPERRNO='||FTPERRNO
   end

   rc = FtpSys( pSys )
   if rc = -1 then do
      say ''
      say 'FtpSys()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say pSys
   end
   /* end of file rxFtpLogoff.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpLogoff 127.0.0.1

   FtpQuote()   FTPERRNO=FTPCOMMAND

   OS/2 operating system

   FtpSys()   FTPERRNO=FTPCOMMAND

Связанныефункции:

FtpAppend(), FtpChDir(), FtpDelete(), FtpDir(), FtpGet(), FtpLs(), FtpMkDir(), FtpPut(), FtpPutUnique(), FtpPwd(), FtpQuote(), FtpRename(), FtpRmDir(), FtpSetActiveMode(), FtpSetBinary(), FtpSetUser(), FtpSite(), FtpSys()

5.9. FtpLs().

Получает список содержимого каталога сервера FTP в сокращённом виде; в списке будут присутствуют только имена файлов и каталогов.

Синтаксис:

rc = FtpLs( pPattern, pStem )

Параметры:

pPattern

шаблон выборки содержимого каталога.
Может содержать имя файла, имя каталога или шаблон имени файла с использованием символов-заменителей '*' и '?'.

Назначение символов-заменителей стандартно:

'?'

заменяет один любой символ в имени

'*'

заменяет любое количество символов в имени

Если в шаблоне не указан путь, то он применяется к содержимому текущего каталога.

pStem

строка, определяющая имя-основу набора переменных, в который будут помещены результаты;
строка обязательно должна заканчиваться точкой ('.').

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpLs() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем, в зависимости от выбранного режима FTP (активный или пассивный), отправляет на сервер одну из следующих последовательностей команд:

   PORT <данные>    активный режим (по умолчанию)
   NLST <содержимое параметра pPattern>
или
   PASV             пассивный режим
   NLST <содержимое параметра pPattern>

Если выполнение прошло успешно, то результатами заполняется набор переменных, имя-основа которых задаётся параметром pStem. Количество записей заносится в переменную из этого набора с индексом 0.

Например, пусть параметр pStem содержит строку 'files.'. Тогда в переменную files.0 будет помещено количество записей в списке, а сами записи будут последовательно помещены в переменные files.1, files.2 и т.д.

Режим FTP нужно переключить заранее функцией FtpSetActiveMode() (по умолчанию, активный).

Примечание:


Строка, передаваемая в параметре pPattern, может содержать имя файла, имя каталога или шаблон имени файла с символами-заменителями '*' и '?'.

Казалось бы, указав в качестве шаблона строку '*', можно получить полный список содержимого текущего каталога.

Однако серверы FTP неоднозначно обрабатывают такой запрос. Некоторые выдают ожидаемый список содержимого текущего каталога. Другие выдают список, в котором отсутствуют имена подкаталогов. Третьи же, выдав список файлов текущего каталога, заодно выдают и списки содержимого подкаталогов текущего каталога.

Поэтому для получения списка содержимого текущего каталога лучше использовать строку '.' (т.е. имя текущего каталога) в качестве параметра.

Такой запрос все серверы FTP обрабатывают однозначно.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и имя каталога на сервере. Азатемотображаетсодержимоеуказанногокаталога.

   /* rxFtpLs.cmd - function example */
   parse arg pHost '/' pDir

   pDir = '/'||Strip( pDir );

   if pHost = '' then do
      say ''
      say 'Usage: rxFtpLs host[/dir]'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   if pDir \= '/' then do
      rc = FtpChDir( pDir )
      if rc = -1 then do
         say ''
         say 'FtpChDir()   FTPERRNO='||FTPERRNO
         signal halt
      end
   end

   rc = FtpLs( '.', 'xFile.' )
   if rc = -1 then do
      say ''
      say 'FtpLs()   FTPERRNO='||FTPERRNO
   end
   else do
      if xFile.0 > 0 then do
         say ''
         do i = 1 to xFile.0
            say xFile.i
         end
      end
   end

   halt:
   rc = FtpLogoff()
   /* end of file rxFtpLs.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpLs 127.0.0.1

   error.log
   Misc Tools
   Public
   ReadMe.txt
   Test.txt

   X:>rxFtpLs ftp.software.ibm.com/pub

   00_Catalog
   00_index
   00_index.tab
   User_Documentation
   User_Documentation.990517.rsr
   dir_structure
   dir_structure.990517.rsr
   index.html
   message.990517.rsr

Связанныефункции:

FtpLogoff(), FtpDir(), FtpSetActiveMode(), FtpSetUser()

 

5.10. FtpMkDir().

Создаёт новый каталог на сервере FTP.

Синтаксис:

rc = FtpMkDir( remoteDir )

Параметры:

remoteDir

имя каталога на сервере FTP

 

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpMkDir() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем отправляет на сервер следующую последовательность команд:

   MKD <содержимое параметра remoteDir>

Если выполнение прошло успешно, то на сервере создаётся новый каталог.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и имя каталога на сервере. Затем создаёт новый каталог, делает его текущим и отображает его имя.

   /* rxFtpMkDir.cmd - function example */
   parse arg pHost '/' pDir

   pDir = '/'||Strip( pDir );

   if pHost = '' | pDir = '/' then do
      say ''
      say 'Usage: rxFtpMkDir host/dir'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpMkDir( pDir )
   if rc = -1 then do
      say ''
      say 'FtpMkDir()   FTPERRNO='||FTPERRNO
      signal halt
   end

   rc = FtpChDir( pDir )
   if rc = -1 then do
      say ''
      say 'FtpChDir()   FTPERRNO='||FTPERRNO
      signal halt
   end

   rc = FtpPwd( xPwd )
   if rc = -1 then do
      say ''
      say 'FtpPwd()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say xPwd
   end

   halt:
   rc = FtpLogoff()
   /* end of file rxFtpMkDir.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpMkDir 127.0.0.1/Data/Ftp/Other

   "E:/data/ftp/other" is current directory.

Связанныефункции:

FtpChDir(), FtpLogoff(), FtpPwd(), FtpRmDir(), FtpSetUser()

5.11. FtpPing().

Проверяет доступность хоста.

Синтаксис:

rc = FtpPing( pHost, pLength )

Параметры:

pHost

имя или адрес хоста

pLength

длина порции данных в пакете ICMP (минимальное значение: 1)

 

Возвращаемое значение:

Функция FtpPing() возвращает одно из следующих значений:

Значение

Описание

<число>

нормальное завершение, ошибок нет;
время в миллисекундах, прошедшее от отправки запроса до получения ответа

PINGREPLY

хост не отвечает

PINGSOCKET

невозможно получить сокет

PINGPROTO

неизвестный протокол ICMP

PINGSEND

передача завершилась с ошибкой

PINGRECV

приём завершился с ошибкой

PINGHOST

неизвестный хост

Cпециальной переменной FTPERRNO всегда присваивается значение 0.

Описание:

Вполне самостоятельная функция, никак не связанная с остальными функциями REXX FTP API (за исключением FtpLoadFuncs() и FtpDropFuncs()). Более того, она даже не использует FTP.

Получив имя хоста в качестве параметра, FtpPing() посылает запрос на получение адреса хоста серверу DNS. Если сервер DNS в системе не определён, то для поиска адреса хоста используется файл TCPIP\ETC\HOSTS.

Затем FtpPing посылает указанному хосту одиночный пакет ICMP "запрос-отклика" ("echo-request") заданной длины и ожидает ответ опрашиваемой системы.

Получив ответ, возвращает в вызывающую функцию число - промежуток времени между посылкой запроса и получением ответа в миллисекундах. Если ответ не пришёл за определённое время, то возвращает код ошибки.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста. А затем проверяет доступность указанного хоста (т.е. "пингует" его).

   /* rxFtpPing.cmd - function example */
   parse arg pHost .

   if pHost = '' then do
      say ''
      say 'Usage: rxFtpPing host'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpPing( pHost, 64 )
   if DataType(rc, 'N') then do
      say ''
      say pHost||'   ping='||rc||'ms'
   end
   else do
      say ''
      say pHost||'   error='||rc
   end
   /* end of file rxFtpPing.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpPing 127.0.0.1

   127.0.0.1   ping=0ms

   X:>rxFtpPing ftp.software.ibm.com

   ftp.software.ibm.com   error=PINGREPLY

Связанные функции:

Связанных функций нет.

5.12. FtpProxy().

Организует копирование файла напрямую с одного сервера на другой.

Синтаксис:

rc = FtpProxy( toHost, toUser, toPass, toAcct,
               fromHost, fromUser, fromPass, fromAcct,
               toFile, fromFile, pMode )

Параметры:

toHost

имя или адрес хоста-получателя

toUser

имя пользователя хоста-получателя

toPass

пароль пользователя хоста-получателя

toAcct

аккаунт пользователя хоста-получателя; если не требуется должна быть указана пустая строка

fromHost

имя или адрес хоста-отправителя

fromUser

имя пользователя хоста-отправителя

fromPass

пароль пользователя хоста-отправителя

fromAcct

аккаунт пользователя хоста-отправителя; если не требуется должна быть указана пустая строка

toFile

имя файла-назначения с указанием пути куда копируется файл

fromFile

имя файла-источника с указанием пути откуда копируется файл

pMode

строка, определяющая режим передачи файлов:

'Ascii'

текстовый

'Binary'

двоичный

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Вполне самостоятельная функция, никак не связанная с остальными функциями REXX FTP API (за исключением FtpLoadFuncs() и FtpDropFuncs()).

Получив имена хостов в качестве параметров, FtpProxy() посылает запросы на получение адресов хостов серверу DNS. Если сервер DNS в системе не определён, то для поиска адресов хостов используется файл TCPIP\ETC\HOSTS.

Затем FtpProxy() соединяется с серверами FTP, работающими на заданных хостах, и отправляет им команды в следующей последовательности:

   Получатель         Отправитель
   ------------------------------
   USER
   PASS
   ACCT
   PWD
   TYPE                            I=Binary, A=Ascii
                      USER
                      PASS
                      ACCT
                      PWD
                      TYPE         I=Binary, A=Ascii
                      PASV
   PORT <данные,
         которые
         вернула
         команда
         PASV
         переданная
         источнику>
   STOR
                      RETR
   QUIT
                      QUIT

вынуждая сервер-получатель получить файл напрямую с сервера-отправителя.

Имя файла-назначения может отличаться от имени файла-источника.

Примечание:

В оригинальной документации отмечено, что параметр, определяющий режим передачи файлов не обязателен. Однако, если его опустить или задать неправильное значение, то FtpProxy() просто вернёт код возврата равный 0, не выполняя никаких действий.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имена или адреса хостов и имена исходного и сохраняемого файлов. А затем организует передачу файла напрямую между серверами.

   /* rxFtpProxy.cmd - function example */
   parse arg pTo pFrom .

  
parse var pTo toHost '/' toFile
   parse var pFrom fromHost '/' fromFile

   toFile = '/'||Strip( toFile )
   fromFile = '/'||Strip( fromFile )

   if toHost = '' | toFile = '/' | fromHost = '' | fromFile = '/' then do
      say ''
      say 'Usage: rxFtpProxy targetHost/targetFile sourceHost/sourceFile'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpProxy( toHost, 'anonymous', 'anonymous@guest.ftp', '', ,
                  fromHost, 'anonymous', 'anonymous@guest.ftp', '', ,
                  toFile, fromFile, 'Binary' )
   if rc = -1 then do
      say ''
      say 'FtpProxy()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say 'File transferred OK'
   end
   /* end of file rxFtpProxy.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpProxy 127.0.0.1/Data/Ftp/x.txt ftp.software.ibm.com/robots.txt

   FtpProxy()   FTPERRNO=FTPCOMMAND

   X:>rxFtpProxy ftp.mydomain.com/robots.txt ftp.software.ibm.com/robots.txt

   File transferred OK

Связанные функции:

Связанных функций нет.

5.13. FtpPut().

Копирует локальный файл с рабочей станции на сервер FTP, заменяя существующий.

Синтаксис:

rc = FtpPut( localFile, remoteFile [, pMode] )

Параметры:

localFile

имя файла на локальной рабочей станции

remoteFile

имя файла на сервере FTP

pMode

(необязательный) строка, определяющая режим передачи файлов:

'Ascii'

текстовый

'Binary'

двоичный

 

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpPut() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем, в зависимости от выбранного режима FTP (активный или пассивный), отправляет на сервер одну из следующих последовательностей команд:

   TYPE        I=Binary, A=Ascii
   PORT <данные>    активный режим (по умолчанию)
   STOR <содержимое параметра remoteFile>
или
   TYPE        I=Binary, A=Ascii
   PASV             пассивный режим
   STOR <содержимое параметра remoteFile>

Если выполнение прошло успешно, то файл на сервере FTP переписывается данными из локального файла на рабочей станции.

Режим FTP нужно переключить заранее функцией FtpSetActiveMode() (по умолчанию, активный).

Если параметр pMode опущен, то выбирается режим передачи файлов ранее установленный функцией FtpSetBinary() (по умолчанию, двоичный).

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя локального файла, имя или адрес хоста и имя файла на сервере. А затем копирует файл с рабочей станции на сервер в файл с указанным именем.

   /* rxFtpPut.cmd - function example */
   parse arg fromFile pHost '/' toFile

   toFile = '/'||Strip( toFile );

   if pHost = '' | toFile = '/' then do
      say ''
      say 'Usage: rxFtpPut localfile host/remotefile'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpPut( fromFile, toFile, 'Binary' )
   if rc = -1 then do
      say ''
      say 'FtpPut()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say 'File '||fromFile||' transferred to '||toFile||' OK'
   end

   rc = FtpLogoff()
   /* end of file rxFtpPut.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpPut xxx.txt 127.0.0.1/Data/Ftp/Test.txt

   File xxx.txt transferred to /Data/Ftp/Test.txt OK

   X:>rxFtpPut C:\readme.txt 127.0.0.1/Data/Ftp/readme.txt

   File C:\readme.txt transferred to /Data/Ftp/readme.txt OK

Связанныефункции:

FtpAppend(), FtpDelete(), FtpLogoff(), FtpGet(), FtpPutUnique(), FtpRename(), FtpSetActiveMode(), FtpSetBinary(), FtpSetUser()

5.14. FtpPutUnique().

Копирует локальный файл с рабочей станции на сервер FTP в файл с уникальным именем.

Синтаксис:

rc = FtpPutUnique( localFile, remoteFile [, pMode] )

Параметры:

localFile

имя файла на локальной рабочей станции

remoteFile

имя файла на сервере FTP

pMode

(необязательный) строка, определяющая режим передачи файлов:

'Ascii'

текстовый

'Binary'

двоичный

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpPutUnique() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем, в зависимости от выбранного режима FTP (активный или пассивный), отправляет на сервер одну из следующих последовательностей команд:

   TYPE        I=Binary, A=Ascii
   PORT <данные>    активный режим (по умолчанию)
   STOU <содержимое параметра remoteFile>
или
   TYPE        I=Binary, A=Ascii
   PASV             пассивный режим
   STOU <содержимое параметра remoteFile>

Если выполнение прошло успешно, то выполняется копирование локального файла рабочей станции на сервер.

Если файл с указанным именем уже существует на сервере, то к имени файла последовательно добавляется индекс 1, 2 и т.д.

Например, если делается попытка сохранить файл readme.txt, а он уже существует, то пробуют сохранить в файл readme1.txt. Если же и он существует, то пытаются сохранить в файл readme2.txt и так до тех пор пока не обнаружится свободное имя файла.

Режим FTP нужно переключить заранее функцией FtpSetActiveMode() (по умолчанию, активный).

Если параметр pMode опущен, то выбирается режим передачи файлов ранее установленный функцией FtpSetBinary() (по умолчанию, двоичный).

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя локального файла, имя или адрес хоста и имя файла на сервере. А затем копирует файл с рабочей станции на сервер в файл с указанным именем.

   /* rxFtpPutUnique.cmd - function example */
   parse arg fromFile pHost '/' toFile

   toFile = '/'||Strip( toFile );

   if pHost = '' | toFile = '/' then do
      say ''
      say 'Usage: rxFtpPutUnique localfile host/remotefile'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpPutUnique( fromFile, toFile, 'Binary' )
   if rc = -1 then do
      say ''
      say 'FtpPutUnique()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say 'File '||fromFile||' transferred to '||toFile||' OK'
   end

   rc = FtpLogoff()
   /* end of file rxFtpPutUnique.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpPutUnique xxx.txt 127.0.0.1/Data/Ftp/Test.txt

   File xxx.txt transferred to /Data/Ftp/Test.txt OK

   X:>rxFtpPutUnique C:\readme.txt 127.0.0.1/Data/Ftp/readme.txt

   File C:\readme.txt transferred to /Data/Ftp/readme.txt OK

Связанныефункции:

FtpAppend(), FtpDelete(), FtpLogoff(), FtpGet(), FtpPut(), FtpRename(), FtpSetActiveMode(), FtpSetBinary(), FtpSetUser()

 

5.15. FtpPwd().

Получает имя текущего каталога на сервере FTP.

Синтаксис:

rc = FtpPwd( pCurDir )

Параметры:

pCurDir

переменная, в которую будет помещена строка, с ответом сервера, содержащим имя текущего каталога.

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpPwd() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем отправляет на сервер следующую последовательность команд:

   PWD

Если выполнение прошло успешно, то помещает ответ сервера в переменную, указанную в качестве параметра pCurDir, если она не инициализирована.

Если переменная инициализирована, то её значение не изменится. Во избежание ошибок рекомендуется сбросить её с помощью команды DROP непосредственно перед вызовом функции.

Имя текущего каталога в ответе сервера всегда заключено в двойные кавычки.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста. А затем отображает ответ сервера с именем текущего каталога.

   /* rxFtpPwd.cmd - function example */
   parse arg pHost .

  
if pHost = '' then do
      say ''
      say 'Usage: rxFtpPwd host'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser()  - Not connected'
      exit 1
   end

   rc = FtpPwd( xPwd )
   if rc = -1 then do
      say ''
      say 'FtpPwd()    FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say xPwd
   end

   rc = FtpLogoff()
   /* end of file rxFtpPwd.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpPwd 127.0.0.1

   "E:/data/ftp" is current directory.

   X:>rxFtpPwd ftp.software.ibm.com

   "/" is current directory.

Связанныефункции:

FtpChDir(), FtpLogoff(), FtpMkDir(), FtpRmDir(), FtpSetUser()

5.16. FtpQuote().

Передаёт команду серверу FTP.

Синтаксис:

rc = FtpQuote( pCmd [, pAnswer] )

Параметры:

pCmd

строка, содержащая команду FTP.

pAnswer

(необязательный) переменная, в которую будет помещена строка, с ответом сервера.

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpQuote() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем отправляет на сервер следующую последовательность команд:

   <содержимое параметра pCmd>

Если выполнение прошло успешно, то помещает ответ сервера в переменную, указанную в качестве параметра pAnswer, если она не инициализирована.

Если переменная инициализирована, то её значение не изменится. Во избежание ошибок рекомендуется сбросить её с помощью команды DROP непосредственно перед вызовом функции.

Сервер должен поддерживать обработку переданной команды FTP.

Примечание:


Про наличие второго параметра в оригинальной документации не упоминается.

Длина строки, возвращаемой во втором параметре, не превышает 197 байт.

Если сервер формирует многострочный ответ, то он искажается, поскольку:

  • все строки ответа могут не поместиться в 197 байт
  • в каждой строке откидываются несколько символов от начала строки и опускаются символы в конце строки

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и команду FTP. Азатемотображаетответсервера.

   /* rxFtpQuote.cmd - function example */
   parse arg pHost pCmd

   if pHost = '' | pCmd = '' then do
      say ''
      say 'Usage: rxFtpQuote host cmd'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpQuote( pCmd, xAnswer )
   if rc = -1 then do
      say ''
      say 'FtpQuote()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say xAnswer
   end

   rc = FtpLogoff()
   /* end of file rxFtpQuote.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpQuote 127.0.0.1 syst

   OS/2 operating system

   X:>rxFtpQuote ftp.software.ibm.com syst

   UNIX Type: L8

   X:>rxFtpQuote 127.0.0.1 type i

   Type set to I (Image/Binary).

   X:>rxFtpQuote ftp.software.ibm.com type i

   TYPE is now 8-bit binary

Связанныефункции:

FtpLogoff(), FtpSite(), FtpSys(), FtpSetUser()

5.17. FtpRename().

Переименовывает файл на сервере FTP.

Синтаксис:

rc = FtpRename( remoteOldFile, remoteNewFile )

Параметры:

 

remoteOldFile

имя существующего файла на сервере FTP

remoteOldFile

новое имя, которое будет присвоено этому файлу

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpRename() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем отправляет на сервер следующую последовательность команд:

   RNFR <содержимое параметра remoteOldFile>
   RNTO <содержимое параметра remoteNewFile>

Если выполнение прошло успешно, то файл на сервере переименовывается.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста, имя файла на сервере и новое имя файла. Азатемпереименовываетуказанныйфайлнасервере.

   /* rxFtpRename.cmd - function example */
   parse arg pHost '/' oldFile newFile

   oldFile = '/'||Strip( oldFile );

   if pHost = '' | oldFile = '/' | newFile = '' then do
      say ''
      say 'Usage: rxFtpRename host/oldfile newfile'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpRename( oldFile, newFile )
   if rc = -1 then do
      say ''
      say 'FtpRename()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say 'File '||oldFile||' renamed to '||newFile||' OK'
   end

   rc = FtpLogoff()
   /* end of file rxFtpRename.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpRename 127.0.0.1/Data/Ftp/Test.txt TestX.txt

   File /Data/Ftp/Test.txt renamed to TestX.txt OK

Связанныефункции:

FtpAppend(), FtpDelete(), FtpGet(), FtpLogoff(), FtpPut(), FtpPutUnique(), FtpSetUser()

5.18. FtpRmDir().

Удаляет каталог на сервере FTP.

Синтаксис:

rc = FtpRmDir( remoteDir )

Параметры:

remoteDir

имя каталога на сервере FTP

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpRmDir() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем отправляет на сервер следующую последовательность команд:

   RMD <содержимое параметра remoteDir>

Если выполнение прошло успешно, то каталог на сервере удаляется.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и имя каталога на сервере. Затемудаляетуказанныйкаталог.

   /* rxFtpRmDir.cmd - function example */
   parse arg pHost '/' pDir

   pDir = '/'||Strip( pDir );

   if pHost = '' | pDir = '/' then do
      say ''
      say 'Usage: rxFtpRmDir host/dir'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpRmDir( pDir )
   if rc = -1 then do
      say ''
      say 'FtpRmDir()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say 'Directory '||pDir||' removed OK'
   end

   rc = FtpLogoff()
   /* end of file rxFtpRmDir.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpRmDir 127.0.0.1/Data/Ftp/Other

   Directory /Data/Ftp/Other removed OK

Связанныефункции:


FtpChDir(), FtpLogoff(), FtpMkDir(), FtpPwd(), FtpSetUser()

5.19. FtpSetActiveMode().

Задаёт режим работы FTP, который будет использоваться функциями REXX FTP API по умолчанию.

Синтаксис:

rc = FtpSetActiveMode( pMode )

Параметры:

pMode

режим FTP:

'0'

пассивный

'1'

активный

Возвращаемое значение:

Функции FtpSetActiveMode(), FtpSetBinary() и FtpSetUser() возвращают одно из следующих значений:

Значение

Описание

1

нормальное завершение, ошибок нет

0

ошибка, требуемое действие не выполнено

Cпециальной переменной FTPERRNO всегда присваивается значение 0.

Описание:

В отличии от функций FtpSetBinary() и FtpSetUser(), которые просто выполняют установку параметров сессии FTP, функция FtpSetActiveMode() сначала проверяет наличие соединения с сервером и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем задаёт режим работы с FTP, который будет использоваться соответствующими функциями REXX FTP API по умолчанию.

В дальнейшем, функции:

FtpAppend()
FtpDir()
FtpGet()

FtpLs()
FtpPut()
FtpPutUnique()

будут использовать режим, установленный функцией FtpSetActiveMode() (по умолчанию, активный).

Примечание:


В оргинальной документации утверждается, что режимом FTP по умолчанию является пассивный режим. На самом деле, по крайней мере для REXX FTP API версии 2.1, по умолчанию используется активный режим FTP.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя локального файла, имя или адрес хоста и имя файла на сервере. А затем копирует файл c сервера в разных режимах работы FTP.

   /* rxFtpSetActiveMode.cmd - function example */
   parse arg toFile pHost '/' fromFile

   fromFile = '/'||Strip( fromFile );

   if pHost = '' | toFile = '/' then do
      say ''
      say 'Usage: rxFtpSetActiveMode localfile host/remotefile'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpSetActiveMode( '0' );
   if rc = 1 then do
      say ''
      say 'FTP mode is passive'
   end
   else do
      say ''
      say 'FtpSetActiveMode("0") error   RC='||rc
      signal halt
   end

   rc = FtpGet( toFile||'.p', fromFile )
   if rc = -1 then do
      say ''
      say 'FtpGet()   FTPERRNO='||FTPERRNO
      signal halt
   end
   else do
      say ''
      say 'File '||fromFile||' received to '||toFile||'.p OK'
   end

   rc = FtpSetActiveMode( '1' );
   if rc = 1 then do
      say ''
      say 'FTP mode is active'
   end
   else do
      say ''
      say 'FtpSetActiveMode("1") error   RC='||rc
      signal halt
   end

   rc = FtpGet( toFile||'.a', fromFile )
   if rc = -1 then do
      say ''
      say 'FtpGet()   FTPERRNO='||FTPERRNO
      signal halt
   end
   else do
      say ''
      say 'File '||fromFile||' received to '||toFile||'.a OK'
   end

   halt:
   rc = FtpLogoff()
   /* end of file rxFtpSetActiveMode.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpSetActiveMode xxx.txt 127.0.0.1/Data/Ftp/Test.txt

   FTP mode is passive

   File /Data/Ftp/Test.txt received to xxx.txt.p OK

   FTP mode is active

   File /Data/Ftp/Test.txt received to xxx.txt.a OK

Связанныефункции:

FtpAppend(), FtpDir(), FtpGet(), FtpLogoff(), FtpLs(), FtpPut(), FtpPutUnique(), FtpSetUser()

5.20. FtpSetBinary().

Задаёт режим передачи файлов, который будет использоваться функциями REXX FTP API по умолчанию.

Синтаксис:

rc = FtpSetBinary( pMode )

Параметры:

pMode

режим передачи файлов:

'Ascii'

текстовый

'Binary'

двоичный

Возвращаемое значение:

Функции FtpSetActiveMode(), FtpSetBinary() и FtpSetUser() возвращают одно из следующих значений:

Значение

Описание

1

нормальное завершение, ошибок нет

0

ошибка, требуемое действие не выполнено

Cпециальной переменной FTPERRNO всегда присваивается значение 0.

Описание:

Если сессия FTP открыта, то функция FtpSetBinary() задаёт режим передачи файлов, который будет использоваться соответствующими функциями REXX FTP API по умолчанию.

В дальнейшем, если при вызове функций:

FtpAppend()
FtpGet()

FtpPut()
FtpPutUnique()

будет опущен параметр, явно определяющий режим передачи файлов, то эти функции будут использовать режим, установленный функцией FtpSetBinary() (по умолчанию, двоичный).

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя локального файла, имя или адрес хоста и имя файла на сервере. А затем копирует файл c сервера в разных режимах передачи.

   /* rxFtpSetBinary.cmd - function example */
   parse arg toFile pHost '/' fromFile

   fromFile = '/'||Strip( fromFile );

   if pHost = '' | toFile = '/' then do
      say ''
      say 'Usage: rxFtpSetBinary localfile host/remotefile'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpSetBinary( 'Binary' );
   if rc = 1 then do
      say ''
      say 'Transfer mode is "Binary"'
   end
   else do
      say ''
      say 'FtpSetBinary("Binary") error   RC='||rc
      signal halt
   end

   rc = FtpGet( toFile||'.b', fromFile )
   if rc = -1 then do
      say ''
      say 'FtpGet()   FTPERRNO='||FTPERRNO
      signal halt
   end
   else do
      say ''
      say 'File '||fromFile||' received to '||toFile||'.b OK'
   end

   rc = FtpSetBinary( 'Ascii' );
   if rc = 1 then do
      say ''
      say 'Transfer mode is "Ascii"'
   end
   else do
      say ''
      say 'FtpSetBinary("Ascii") error   RC='||rc
      signal halt
   end

   rc = FtpGet( toFile||'.a', fromFile )
   if rc = -1 then do
      say ''
      say 'FtpGet()   FTPERRNO='||FTPERRNO
      signal halt
   end
   else do
      say ''
      say 'File '||fromFile||' received to '||toFile||'.a OK'
   end

   halt:
   rc = FtpLogoff()
   /* end of file rxFtpSetBinary.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpSetBinary xxx.txt 127.0.0.1/Data/Ftp/Test.txt

   Transfer mode is "Binary"

   File /Data/Ftp/Test.txt received to xxx.txt.b OK

   Transfer mode is "Ascii"

   File /Data/Ftp/Test.txt received to xxx.txt.a OK

Связанныефункции:

FtpAppend(), FtpGet(), FtpLogoff(), FtpPut(), FtpPutUnique(), FtpSetUser()

5.21. FtpSetUser().

Открывает сессию FTP.

Синтаксис:

rc = FtpSetUser( pHost, pUser, pPass [, pAcct] )

Параметры:

pHost

адрес или имя хоста (сервера FTP)

pUser

имя пользователя сервера FTP

pPass

пароль пользователя сервера FTP

pAcct

(необязательный) аккаунт пользователя сервера FTP; информация об аккаунте пользователя, зависящая от конкретного хоста

Возвращаемое значение:

Функции FtpSetActiveMode(), FtpSetBinary() и FtpSetUser() возвращают одно из следующих значений:

Значение

Описание

1

нормальное завершение, ошибок нет

0

ошибка, требуемое действие не выполнено

Cпециальной переменной FTPERRNO всегда присваивается значение 0.

Описание:

Функция FtpSetUser() открывает сессию FTP, задавая имя или адрес хоста, имя пользователя, пароль и аккаунт.

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

Фактически соединение с сервером FTP будет выполнено при первом же вызове любой функции из перечисленных ниже:

FtpAppend()
FtpChDir()
FtpDelete()
FtpDir()
FtpGet()
FtpLs()

FtpMkDir()
FtpPut()
FtpPutUnique()
FtpPwd()
FtpQuote()
FtpRename()

FtpRmDir()
FtpSetActiveMode()
FtpSite()
FtpSys()

Именно тогда, перед выполнением вызванной функции, сначала будет послан запрос на получение адреса хоста серверу DNS. Если сервер DNS в системе не определён, то для поиска адреса хоста используется файл TCPIP\ETC\HOSTS.

Затем будет установлено соединение с сервером FTP и выполнена следующая последовательность команд:

   USER <содержимое параметра pUser>
   PASS <содержимое параметра pPass>
   ACCT <содержимое параметра pAcct>
   PWD

и только потом будут выполнены действия вызванной функции.

Все установки, выполненнные функцией FtpSetUser(), сбрасывает функция FtpLogoff(), закрывая сессию FTP.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста. Затем отправляет на сервер неполную команду, после чего сервер по тайм-ауту разрывает соединение. Соединение автоматически восстанавливается во время следующей попытки доступа к серверу. Затемсессиязакрываетсяиработастановитсяневозможна.

   /* rxFtpLogoff.cmd - function example */
   parse arg pHost

   if pHost = '' then do
      say ''
      say 'Usage: rxFtpLogoff host'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpQuote( 'TYPE', xAnswer )
   if rc = -1 then do
      say ''
      say 'FtpQuote()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say xAnswer
   end

   rc = FtpSys( pSys )
   if rc = -1 then do
      say ''
      say 'FtpSys()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say pSys
   end

   rc = FtpLogoff()

   if rc = -1 then do
      say ''
      say 'FtpLogoff()   FTPERRNO='||FTPERRNO
   end

   rc = FtpSys( pSys )
   if rc = -1 then do
      say ''
      say 'FtpSys()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say pSys
   end
   /* end of file rxFtpLogoff.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpLogoff 127.0.0.1

   FtpQuote()   FTPERRNO=FTPCOMMAND

   OS/2 operating system

   FtpSys()   FTPERRNO=FTPCOMMAND

Связанныефункции:

FtpAppend(), FtpChDir(), FtpDelete(), FtpDir(), FtpGet(), FtpLogoff(), FtpLs(), FtpMkDir(), FtpPut(), FtpPutUnique(), FtpPwd(), FtpQuote(), FtpRename(), FtpRmDir(), FtpSetActiveMode(), FtpSetBinary(), FtpSite(), FtpSys()

5.22. FtpSite().

Передаёт информационную строку серверу FTP.

Синтаксис:

rc = FtpSite( pInfo )

Параметры:

pInfo

информационная строка для сервера FTP.

Возвращаемое значение:

Функция возвращает одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpSite() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем отправляет на сервер следующую последовательность команд:

   SITE <содержимое параметра pInfo>

Сервер должен поддерживать обработку переданной информационной строки.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста и информационную строку. Азатемотображаетрезультатпередачи.

   /* rxFtpSite.cmd - function example */
   parse arg pHost pInfo

   if pHost = '' then do
      say ''
      say 'Usage: rxFtpSite host info'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpSite( pInfo )
   if rc = -1 then do
      say ''
      say 'FtpSite()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say 'Information transfered OK'
   end

   rc = FtpLogoff()
   /* end of file rxFtpSite.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpSite 127.0.0.1 xxx

   Information transfered OK

   X:>rxFtpSite ftp.software.ibm.com xxx

   FtpSite()   FTPERRNO=FTPCOMMAND

Связанныефункции:


FtpLogoff(), FtpQuote(), FtpSys(), FtpSetUser()

5.23. FtpSys().

Получает информацию об операционной системе сервера FTP.

Синтаксис:

rc = FtpSys( pAnswer )

Параметры:

pAnswer

переменная, в которую будет помещена строка с информацией об операционной системе сервера.

Возвращаемое значение:

Функция FtpSys возвращает одно из следующих значений:

Значение

Описание

<строка>

нормальное завершение, ошибок нет;
строка содержит описание операционной системы сервера FTP;
специальной переменной FTPERRNO присвоено значение 0

-1

ошибка во время выполнения;
код ошибки помещён в специальную переменную FTPERRNO

Специальной переменной FTPERRNO присваивается одно из следующих значений:

Значение

Описание

0

нормальное завершение, ошибок нет

FTPSERVICE

неизвестный сервис

FTPHOST

неизвестный хост

FTPSOCKET

невозможно получить сокет

FTPCONNECT

невозможно соединиться с сервером

FTPLOGIN

регистрация не выполнена

FTPABORT

передача данных прервана

FTPLOCALFILE

проблемы с открытием локального файла

FTPDATACONN

проблемы с инициализацией соединения

FTPCOMMAND

выполнение команды прервано, соединение с сервером может быть разорвано

FTPPROXYTHIRD

прокси-сервер не поддерживает передачу третьей стороне

FTPNOPRIMARY

нет первичного соединения для передачи по доверенности (proxy transfer)

FTPFAILURE

команда не выполнена, соединение с сервером сохранено

Описание:

Если сессия FTP открыта, то сначала функция FtpSys() проверяет наличие соединения с сервером FTP и устанавливает его, если оно ещё не было установлено, или восстанавливает его, если оно было разорвано.

Имя или адрес сервера, имя пользователя и пароль задаются при открытии сессии FTP функцией FtpSetUser().

Затем отправляет на сервер следующую последовательность команд:

   SYST

Если выполнение прошло успешно, то помещает информацию об операционной системе сервера в переменную, указанную в качестве параметра pAnswer, если она не инициализирована.

Если переменная инициализирована, то её значение не изменится. Во избежание ошибок рекомендуется сбросить её с помощью команды DROP непосредственно перед вызовом функции.

Пример:

Ниже приведён текст программы, которая в качестве параметров получает имя или адрес хоста. А затем отображает описание операционной системы, под которой работает сервер на этом хосте.

   /* rxFtpSys.cmd - function example */
   parse arg pHost .

   if pHost = '' then do
      say ''
      say 'Usage: rxFtpSys host'
      say ''
      exit 1
   end

   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpSetUser( pHost, 'anonymous', 'anonymous@guest.ftp' )
   if rc \= 1 then do
      say 'FtpSetUser() - Not connected'
      exit 1
   end

   rc = FtpSys( xSys )
   if rc = -1 then do
      say ''
      say 'FtpSys()   FTPERRNO='||FTPERRNO
   end
   else do
      say ''
      say rc
   end

   rc = FtpLogoff()
   /* end of file rxFtpSys.cmd */

Примерырезультатоввыполнения:

   X:>rxFtpSys 127.0.0.1

   OS/2 operating system

   X:>rxFtpSys ftp.software.ibm.com

   UNIX Type: L8

Связанныефункции:


FtpLogoff(), FtpQuote(), FtpSite(), FtpSetUser()

5.24. FtpVersion().

Получаетверсиюбилиотеки REXX FTP API.

Синтаксис:

rc = FtpVersion( pAnswer )

Параметры:

pAnswer

переменная, в которую будет помещён номер версии библиотеки REXX FTP API.

Возвращаемое значение:

Функция FtpVersion() всегда возвращает пустую строку ("").
Cпециальной переменной FTPERRNO всегда присваивается значение 0.

Описание:

Вполне самостоятельная функция, никак не связанная с остальными функциями REXX FTP API (за исключением FtpLoadFuncs() и FtpDropFuncs()).

Всегда возвращает пустую строку в качестве кода возврата и помещает номер версии REXX FTP API в переменную, указанную в качестве параметра pAnswer, если она не инициализирована.

Если переменная инициализирована, то её значение не изменится. Во избежание ошибок рекомендуется сбросить её с помощью команды DROP непосредственно перед вызовом функции.

Пример:


Ниже приведён текст программы, которая демонстрирует номер версии библиотеки REXX FTP API.

   /* rxFtpVersion.cmd - function example */
   if RxFuncQuery( 'FtpLoadFuncs' ) then do
      rc = RxFuncAdd( 'FtpLoadFuncs', 'rxFtp', 'FtpLoadFuncs' )
      rc = FtpLoadFuncs( )
   end

   rc = FtpVersion( pVer )
   say ''
   say 'REXX FTP API Version '||pVer
   /* end of file rxFtpVersion.cmd */

Примеры результатов выполнения:

   X:>rxFtpVersion

   REXX FTP API Version 2.1

Связанные функции:


Связанных функций нет.

 

6. Замечания по применению.

В этом разделе автор попытался обобщить свой опыт применения REXX FTP API, чтобы показать не только КАК ИСПОЛЬЗОВАТЬ ту или иную функцию, но и ЧТО ПРОИСХОДИТ во время работы.

Для иллюстрации отдельных пунктов использованы программы, тексты которых приведены в разделе "Пример" описания соответствующих функций.

Отметим, что примеры выполнялись в операционной системе The Operating System/2 Version 4.50 Revision 14.088. В качестве сервера FTP использовался стандартный модуль ftpd из поставки OS/2 (хост 127.0.0.1).

Некоторые замечания уже были приведены в соответствующих разделах.

6.1. Активный и пассивный режимы FTP.

FTP использует два раздельных канала TCP/IP:

  • один - для передачи управляющих команд,
  • другой - для передачи данных.

Режимы работы FTP различаются по направлению инициирования канала данных:

активный

соединение для передачи команд инициирует клиент, а соединение для передачи данных - сервер,

пассивный

оба соединения инициирует клиент.

  1. Активный режим FTP.

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

    Делается это с помощью команды:

   PORT a1,a2,a3,a4,p1,p2
        -+--------- -+---
         |           |
         |           +--- номер порта = 256*p1+p2
         +--------------- ip-адрес клиента

Пример получения клиентом файла с сервера FTP в активном режиме:

Клиент (192.168.2.22)       Порты и направление   Сервер (10.10.15.254)
------------------------------------------------------------------------------
Oткрывает свободный динамический порт (например, 51618) под канал управления.

Инициирует
каналуправления (51618 -------> 21)
                            (51618 <------- 21)   220 FTP server ready.
USER                 (51618 -------> 21)
                            (51618 <------- 21)   331 Login ok, send password.
PASS              (51618 -------> 21)
                            (51618 <------- 21)   230 Login ok.
PWD                         (51618 -------> 21)
                            (51618 <------- 21)   257 "/" is current directory.
TYPE I                      (51618 -------> 21)
                            (51618 <------- 21)   200 Type set to I.


Oткрывает свободный динамический порт (например, 51619) под канал данных
и начинает его прослушивать, ожидая данных.

PORT 192,168,2,22,201,163.  (51618 -------> 21)
                            (51618 <------- 21)   200 PORT command successful.
RETR Test.txt               (51618 -------> 21)

                            (51619 <------- 20)   Инициирует канал данных
                            (51619 <------- 20)   Передаёт данные
                            (51619 <------- 20)   Закрывает канал данных

                            (51618 <------- 21)   226 Transfer complete.

Закрывает динамический порт, открытый под канал данных.

QUIT                        (51618 -------> 21)
                            (51618 <------- 21)   221 Goodbye.

Закрывает канал управления. (51618 -------> 21)

  1. Пассивный режим FTP.

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

    Сервер делает это, отвечая на команду PASV:

   227 Entering Passive Mode (a1,a2,a3,a4,p1,p2).
                             
-+--------- -+---
                               |           |
                               |           +--- номер порта = 256*p1+p2
                               +--------------- ip-адрес сервера

Пример получения клиентом файла с сервера FTP в пассивном режиме:

Клиент (192.168.2.22)       Порты и направление   Сервер (10.10.15.254)
------------------------------------------------------------------------------
Oткрывает свободный динамический порт (например, 51618) под канал управления.

Инициирует
каналуправления (51618 -------> 21)
                            (51618 <------- 21)   220 FTP server ready.
USER                 (51618 -------> 21)
                            (51618 <------- 21)   331 Login ok, send password.
PASS              (51618 -------> 21)
                            (51618 <------- 21)   230 Login ok.
PWD                         (51618 -------> 21)
                            (51618 <------- 21)   257 "/" is current directory.
TYPE I                      (51618 -------> 21)
                            (51618 <------- 21)   200 Type set to I.
PASV                        (51618 -------> 21)

                                                  
Выделяет
порт (например, 27087) подканалданных

                            (51618 <------- 21)   227 Entering Passive Mode (10,10,15,254,105,207).

O
ткрывает
свободныйдинамическийпорт (например, 51619) подканалданных.

Инициируетканалданных     (51619 ----> 27087)

RETR Test.txt               (51618 -------> 21)
                            (51618 <------- 21)   150 Opening BINARY mode data connection for /Test.txt (75 bytes).

                           
(51619 <---- 27087)   Передаёт данные
                            (51619 <---- 27087)   Закрывает канал данных

                            (51618 <------- 21)   226 Transfer complete.

Закрывает динамический порт, открытый под канал данных.

QUIT                        (51618 -------> 21)
                            (51618 <------- 21)   221 Goodbye.

Закрывает канал управления. (51618 -------> 21)

Строго говоря, пассивный режим был придуман для преодоления проблем, возникающих из-за использования firewall/NAT, которыми защищена рабочая станция клиента, находящаяся в локальной сети.

Однако, практически все современные firewall/NAT, позволяют рабочим станциям клиента, находящимся в локальной сети, работать с серверами FTP, расположенными во внешней сети, в активном режиме:

  • firewall/NAT, защищающий локальную сеть клиента, перехватывает команду PORT, отправляемую из локальной сети во внешнюю,
  • в перехваченной команде PORT подменяет локальный адрес рабочей станции на внешний адрес firewall/NAT,
  • строит временное правило firewall, разрешающее доступ с порта 20 внешнего сервера на порт, указанный в перехваченной команде,
  • строит временное правило NAT, направляющее трафик между портом 20 внешнего сервера и портом, указанным в перехваченной команде, на соответствующую рабочую станцию в локальной сети.

Аналогичным образом могут быть защищены и серверы FTP, когда они размещены в локальной сети (чаще говорят про "демилитаризованную зону", но она тоже представляет из себя локальную сеть, только отделённую от основной как логически, так и физически).

В этом случае "умный" firewall/NAT, защищающий серверы:

  • перехватывает ответ на команду PASV, отправляемый сервером клиенту во внешнюю сеть,
  • в перехваченном ответе подменяет локальный адрес сервера на внешний адрес firewall/NAT,
  • строит временное правило firewall, разрешающее доступ с любого порта внешнего клиента на порт, указанный в перехваченном ответе,
  • строит временное правило NAT, направляющее трафик между любым портом внешнего клиента и портом, указанным в перехваченном ответе, на соответствующий сервер в локальной сети.

Но это тоже может не решить все проблемы, связанные с использованием firewall/NAT.

Иногда возникает ситуация, которая со стороны клиента внешне выглядит так:

  • не удаётся скачать файл с сервера FTP с помощью функций REXX FTP API в пассивном режиме, хотя с помощью браузера (например, Firefox), который тоже использует пассивный режим, файл скачивается.

Эта проблема возникает из-за того, что в строке, получаемой клиентом в ответ на команду PASV, указан адрес, отличный от адреса сервера FTP. И, если браузер просто игнорирует этот адрес, то функции REXX FTP API пытаются установить соединение для передачи данных именно по адресу, указанному в ответе.

В этом случае надо использовать активный режим для функций REXX FTP API, если разрешит администратор безопасности сети.

6.2. Восстановление соединения.

Функция FtpSetUser() открывает сессию FTP, задавая имя или адрес хоста, имя пользователя, пароль и аккаунт.

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

Фактически, как инициализация, так и восстановление соединения с сервером FTP выполняется при вызове любой функции из перечисленных ниже, если сессия FTP открыта, но соединение с сервером отсутствует:

FtpAppend()
FtpChDir()
FtpDelete()
FtpDir()
FtpGet()
FtpLs()

FtpMkDir()
FtpPut()
FtpPutUnique()
FtpPwd()
FtpQuote()
FtpRename()

FtpRmDir()
FtpSetActiveMode()
FtpSite()
FtpSys()

 

  1. Инициализация соединения.

    Выполняется, если соединение с сервером ещё ни разу не устанавливалось после вызова FtpSetUser().

    Сначала посылается запрос на получение адреса хоста серверу DNS. Если сервер DNS в системе не определён, то для поиска адреса хоста используется файл TCPIP\ETC\HOSTS.

    Затем устанавливается соединение с сервером FTP и выполняется следующая последовательность команд:

   USER
   PASS
   ACCT
   PWD

  1. Восстановление соединения.

    Выполняется, если соединение с сервером было разорвано во время выполнения.

    Сначала устанавливается соединение с сервером FTP. Затем выполняется следующая последовательность команд:

   USER
   PASS
   ACCT
  
С
WD 

где directory - имя текущего каталога на момент разрыва соединения.

 

6.3. О полезности FtpSys().

FtpSys() выдаёт информацию об операционной системе, под которой работает сервер FTP, а иногда и о нём самом. Эту информацию можно использовать для вынесения некоторых предположений о том, что можно ожидать от данного сервера.

Например, в каком формате будет предоставляться список содержимого каталога, формируемого функцией FtpDir(). Или, как будет выглядеть имя текущего каталоге в строке, возвращаемой функцией FtpPwd().

Многое, конечно, зависит от фантазии автора исходного кода конкретного сервера FTP и умения администратора, настроившего его на рабочем месте, но всё-таки какие-то основные правила обычно соблюдаются.

Примеры ответов некоторых серверов FTP на запрос информации об операционной системе:

   Сервер                 Ответ
   -------------------------------------------------------------
   ftp.os2.ru             OS/2 operating system
   os2.fannet.ru          UNIX type:OS/2
   ftp.software.ibm.com   UNIX Type: L8
   ftp.relcom.ru          UNIX Type: L8 Version: BSD-199506
   ftp.demos.su           UNIX Type: L8 Version: tnftpd 20080609
   ftp.sun.com            UNIX Type: L8 Version: SUNOS
   ftp.asus.com           UNIX emulated by FileZilla
   ftp.gnupg.org          UNIX
   ftp.microsoft.com      Windows_NT
   ftp.softlab.ru         Windows_NT version 5.0
   ftp.mt.xplain.com      MACOS Peter's Server

Итак, что же можно ожидать от сервера FTP, получив от него информацию об операционной системе:

  1. UNIX ...
    1. Независимо от операционной системы, под которой работает данный сервер FTP, функция FtpDir() будет возвращать списки содержимого каталогов в UNIX-подобном формате:

      Пример 1:

   X:>rxFtpDir ftp.software.ibm.com

   <...пропуск...>
   drwxr-sr-x   7 102004493 201    256 Mar  9 2004  ps
   lrwxrwxrwx   1 102004493 1       14 Sep 25 2009  pub -> software/lotus
   drwxr-sr-x  19 102004493 201   4096 Jul 22 1999  publications
   -rw-r--r--   1 102004493 201     75 Feb 16 08:52 robots.txt
   drwxr-sr-x  21 102004493 201   4096 Aug 20 2002  rs6000
   drwxr-sr-x  38 102004493 201   4096 Apr 28 2008  s390
   <...пропуск...>

где каждая запись состоит из нескольких полей, разделённых пробелами. Большинство реализаций серверов FTP формирует записи, состоящие из 9 полей, но встречаются и такие, которые формируют записи из 8 полей (например, DeleGate).

Важно тут то, что первое поле всегда содержит тип записи и права доступа для владельца, группы и остальных пользователей, а в последних пяти всегда последовательно располагаются длина, месяц, число, год (или время) создания/модификации файла и, наконец, имя.

Тип записи определяется по первому символу первого поля (подсвечен в вышеприведённом примере):
d - каталог, l - линк, - - файл и т.д.

Имя всегда находится в последнем поле (подсвечено в вышеприведённом примере) и может само содержать пробелы, что несколько усложняет разбор из-за разницы числа полей в записи для разных серверов.

  1. Домашний каталог будет корневым:

    Пример 2:

   X:>rxFtpPwd ftp.software.ibm.com

   "/" is your current location

  1. Функция FtpPwd() возвращает имя текущего каталога так, как оно хранится в файловой системе, включая прописные и строчные буквы:

    Пример 3:

   X:>rxFtpDir ftp.dlink.ru/pub

   drwxrwsr-x   73 33       106   4096 Apr  5 09:24 ADSL
   drwxrwsr-x   57 33       106   4096 Dec 17 14:43 Adapter
   drwxrwsr-x   13 33       106   4096 Feb  1  2006 Bootrom
   <...пропуск...>

   X:>rxFtpChDir ftp.dlink.ru/pub/Bootrom

   "/pub/Bootrom" is your current location

  1. Тем не менее могут быть незначительные различия в работе функций с серверами различного исполнения:
    • в списках содержимого каталогов (FtpDir()) могут присутствовать записи типа total:

   total 208
   drwxr-sr-x  13 102004493 201   4096 Apr 18 2008  4700
   -rw-r--r--   1 102004493 201   6981 Dec 20 1995  TRADEMARKS.TXT
   <...
пропуск
...>

в начале или в конце списка,

  • в списках содержимого каталогов (FtpDir()) могут присутствовать записи текущего и родительского каталогов:

   dr--r--r--  1 ftp      -----      0 Jan  2  1980 .
   dr--r--r--  1 ftp      -----      0 Jan  2  1980 ..
  
dr--r--r--  1 ftp      -----      0 Dec 19  2007 fido
   <...пропуск...>

в начале списка,

  • в имени текущего каталога (FtpPwd) может присутствовать закрывающий символ '/':

   "/pub/" is your current location

  1. OS/2 operating system

    Такую строку выдаёт стандартный модуль ftpd из поставки OS/2.
    1. Функция FtpDir() будет возвращать списки содержимого каталогов в неповторимой полуосёвой манере:

      Пример 4:

   X:>rxFtpDir 127.0.0.1

   351      A          04-11-10   11:10  error.log
     0      A    DIR   04-12-10   08:59  Misc Tools
     0           DIR   04-10-10   08:33  Public
    50                 04-10-10   08:34  ReadMe.txt
    10      A          04-10-10   13:57  Test.txt

Конечно, строго говоря, здесь каждая запись состоит из 6 полей, разделённых пробелами.

Во втором поле перечисляются атрибуты файла.
В третьем - индикатор каталога.
В шестом - имя, которое само может содержать пробелы.

Однако, поля атрибутов и индикатора каталога могут быть пустыми (заполнены пробелами), что несколько усложняет разбор.

Если каталог пуст, то выдаётся единственная запись:

   total 0

  1. Домашний каталог будет содержать полный путь, включая букву диска:

    Пример 5:

   X:>rxFtpPwd 127.0.0.1

   "E:/data/ftp" is current directory.

что надо учитывать при переходах от корня. В программах, используемых здесь в качестве примера, как раз применяется механизм перехода от корня:

Пример 6:

   X:>rxFtpChDir 127.0.0.1/Public

   FtpChDir
   FTPERRNO=FTPCOMMAND

   X:>rxFtpChDir 127.0.0.1/data/ftp/Public

   "E:/data/ftp/public" is current directory.

  1. Функция FtpPwd() возвращает имя текущего каталога исключительно строчными буквами:

    Пример 7:

   X:>rxFtpDir 127.0.0.1

   351      A          04-11-10   11:10  error.log
     0      A    DIR   04-12-10   08:59  Misc Tools
     0           DIR   04-10-10   08:33  Public
    50                 04-10-10   08:34  ReadMe.txt
    10      A          04-10-10   13:57  Test.txt

   X:>rxFtpChDir 127.0.0.1/data/ftp/Public

   "E:/data/ftp/public" is current directory.

  1. Windows_NT

    Так идентифицируются, по всей видимости, Microsoft IIS с версией меньше 5.
    1. Функция FtpDir() будет возвращать списки содержимого каталогов в стиле Windows:

      Пример 8:

   X:>rxFtpDir ftp.microsoft.com/MISC

   08-05-09  01:13PM      

          beckyk
   04-08-94  06:13PM                15749 CBCP.TXT
   08-05-09  01:13PM      
          csformat
   08-05-09  01:13PM      
          DAILYKB
   04-12-93  05:30PM                  710 DISCLAIM.TXT
   <...пропуск...>

 

Конечно, строго говоря, здесь каждая запись состоит из 5 полей, разделённых пробелами.

В третьем поле отображается индикатор каталога.
В четвёртом - длина файла.
В пятом - имя, которое само может содержать пробелы.

Однако, для записей каталогов заполняется пробелами поле длины, а для записей файлов пробелами заполняется поле индикатора каталога, что и облегчает разбор, сводя всё к четырём полям.

  1. Остальные замечания аналогичны UNIX ... серверам.
  1. Windows_NT version 5.0

    Так идентифицируются, по всей видимости, Microsoft IIS с версией 5 и выше.

    Все замечания аналогичны UNIX ... серверам.
  2. MACOS Peter's Server

    Понятно, что это некий сервер под MACOS. Дальше мысль останавливается :)
  3. Функция FtpDir() будет возвращать списки содержимого каталогов в формате, похожем на формат UNIX:

    Пример 9:

   X:>rxFtpDir ftp.mt.xplain.com

   -rwxr-xr-x        0         214      214 Jun 30  2005 !readme
   drwxr-xr-x               folder        0 Jul 17  2006 adsales
   drwxr-xr-x               folder        0 Jul 17  2006 challenge
   <...пропуск...>
   drwxr-xr-x               folder        0 Jul 17  2006 thinkref
   drwxr-xr-x               folder        0 Jul 17  2006 util
   -rwxr-xr-x      332           7      339 Feb  5  2040 welcome.txt

Конечно, строго говоря, здесь каждая запись состоит из 8 полей, разделённых пробелами.

Первое поле содержит тип записи и права доступа для владельца, группы и остальных пользователей,
В третьем поле отображается индикатор каталога, который так же присутствует в первом символе первого поля.
В четвёртом - длина файла.
В пятом, шестом и седьмом - месяц, число и год (или время) создания/модификации файла, соответственно.
В восьмом - имя, которое само может содержать пробелы.

Однако, для записей каталогов второе поле заполняется пробелами. Поэтому при разборе можно считать, что записи каталогов содержат 7 полей, а записи файлов - 8.

  1. Остальные замечания аналогичны UNIX ... серверам.

6.4. Отличия FTPFAILURE и FTPCOMMAND.

В оригинальной документации значение FTPFAILURE отсутствует в списке возможных значений, которые может получать специальная переменная FTPERRNO.

Состояние FTPFAILURE похоже на состояние FTPCOMMAND, но отличается механизмом возникновения и результатом.

Пример 1:

   X:>rxFtpQuote 127.0.0.1 XXX

   FtpQuote()   FTPERRNO=FTPFAILURE

В этом примере серверу, работающему на хосте 127.0.0.1, передается команда

   XXX

Поскольку эта команда не реализована в данном сервере FTP, то в ответ он посылает сообщение:

   502 Unknown command.

В результате, обработчик возврата функции REXX FTP API формирует состояние FTPFAILURE в специальной переменной FTPERRNO. Соединение с сервером не разрывается.

Пример 2:

   X:>rxFtpQuote 127.0.0.1 TYPE

   FtpQuote()   FTPERRNO=FTPCOMMAND

В этом примере серверу, работающему на хосте 127.0.0.1, передается команда

   TYPE

Эта команда реализована в сервере FTP, но в данном случае записана не полностью (отсутствует обязательный параметр). Сервер, начав выполнение команды, ожидает получения недостающего параметра и, не дождавшись, прекращает выполнение команды. Послечегопосылаетсообщение:

   221 You could at least say goodbye.

и разрывает соединение.

В результате, обработчик возврата функции REXX FTP API формирует состояние FTPCOMMAND в специальной переменной FTPERRNO. Соединение с сервером разорвано по инициативе сервера.

6.5. Проблемы и недостатки.

  1. Неполная поставка

    В некоторых случаях при возникновении ошибок библиотека может самостоятельно выводить на устройство stderr (обычно, консоль) диагностические сообщения. Например, возникновение ошибки FTPABORT может сопровождаться сообщением:

   abort: The file or directory specified cannot be found.

Файл сообщений об ошибках DDE4.MSG должен находиться в одном из каталогов, перечисленных в переменной окружения DPATH, задаваемой в файле CONFIG.SYS.

Одним из недостатков является то, что вывод этих сообщений невозможно подавить, а другим - то, что файл DDE4.MSG отсутствует в поставке OS/2. Надо добавить, что в версиях eComStation, использующих LANGE, он присутствует.

  1. Неполная реализация

    К сожалению, в REXX FTP API реализованы далеко не все функции OS/2 FTP API, чей надстройкой он, в сущности, и является.

    Кроме того, и в самом OS/2 FTP API отсутствуют некоторые полезные функции, реализующие, например, докачку файлов с сервера FTP.
  2. Искажение ответа сервера FTP в FtpQuote()

    Недостатком является уже то, что в оригинальной документации не упоминается про наличие у функции второго параметра, в который помещается ответ сервера FTP на переданную ему команду.

    Более существенный недостаток состоит в том, что ответ сервера FTP искажается:
    • обрезается до 197 символов,
    • в каждой строке откидываются несколько символов от начала строки и опускаются символы в конце строки, что особенно сказывается на многострочных ответах.
  3. Наивная реализация пассивного режима

    Серверы FTP могут быть защищены с помощью firewall/NAT, когда они располагаются в локальной сети (чаще говорят про "демилитаризованную зону", но она тоже представляет из себя локальную сеть, только отделённую от основной как логически, так и физически).

    Соответственно, ответ сервера на команду PASV будет корректироваться "умным" firewall/NAT, защищающим сервер, с целью замены в нём локального адреса сервера на внешний адрес firewall/NAT. В зависимости от фантазии строителя сети, в которой находится сервер FTP, ответ сервера может пройти через несколько "умных" firewall/NAT пока доберётся до клиента. И каждый такой "умный" firewall/NAT возможно будет корректировать данные ответа.

    В результате до клиента может добраться ответ, в котором указан адрес, несоответствующий адресу сервера FTP.

    И, если ушлые браузеры, использующие пассивный режим (например, Firefox), игнорируют этот адрес и строят канал передачи данных с тем же сервером, с которым установлено управляющее соединение, то функции REXX FTP API честно пытаются соединиться с хостом, чей адрес указан в ответе.
  4. Проблемы FtpProxy()
  5. Документирование

    В оригинальной документации отмечено, что параметр, определяющий режим передачи файлов, не обязателен. Однако, если его опустить или задать неправильное значение, то FtpProxy() просто вернёт код возврата равный 0, не выполняя никаких действий, что затрудняет диагностику ошибок.
  6. Функционирование

    Порождаются самой схемой работы функции:
    • потоки управляющих команд организуются между хостом, на котором выполняется программа, использующая FtpProxy(), и серверами,
    • потоки данных организуются между серверами напрямую.

Поэтому работоспособность функции сильно зависит от наличия различных firewall/NAT не только между хостом и серверами, которыми он управляет, но и между самими серверами FTP.

Кроме того, серверы FTP могут проверять адрес, передаваемый в команде PORT, на соответствие адресу хоста, с которого осуществляется управление, и запрещать работу при несовпадении.

  1. Невозврат из функций REXX FTP API

    Иногда наблюдается невозврат из функций REXX FTP API, приводящий к зависанию программ. Проявление этого эффекта было отмечено в некоторых программах, которые в течение одного сеанса многократно обращаются к серверу, например, в программе построения дерева каталогов сервера FTP.

    Оказывается, функции REXX FTP API во время выполнения цепочек команд обильно уснащают процесс общения с сервером FTP командами NOOP. И, если передача значащих команд и получение ответов на них контролируется жёстко (выполняется повторная отправка команд каждые 64 секунды, через определённое количество неудачных попыток соединение разрывается и формируется соответствующая ошибка), то обработчик ошибок самовольно вставленных команд NOOP не так строг (повторная отправка команды не выполняется, соединение остаётся в состоянии ESTABLISHED до тех пор, пока не будет закрыто каким-либо способом).

    Например, если функция FtpChDir() присутствует в цепочке других команд, то дополнительные команды NOOP могут быть выданы как перед командой CWD, так и после неё.

    В этом случае неполучение ответа на команду CWD приведёт к возникновению соответствующей ошибки, а неполучение ответа на команду NOOP, самовольно добавленную REXX FTP API, приводит к невыходу из функции FtpChDir() (по крайней мере, до закрытия соединения).

    Надо сказать, что эта ситуация возникает далеко не со всеми серверами FTP и, видимо, сильно зависит от настроек конкретного экземпляра сервера.
  2. Несоответствие оригинальной документации реальному исполнению

    Оригинальная документация достаточно скупа. Кроме того, в ряде случаев она содержит утверждения прямо противоположные действительности.

    Например, утверждается, что по умолчанию функции REXX FTP API используют пассивный режим FTP, хотя на самом деле по умолчанию используется активный режим.

7. Послесловие.

Благодарности:

Автор благодарен Joseph Sharo за ряд ценных критических замечаний и предоставление доступа к своему серверу FTP для проведения ряда экспериментов.

Первоисточники:

  • TCP/IP REXX FTP API Referenceизсостава OS/2 (файл rxFtp.inf)
    (C)Copyright International Business Machines Corporation 1996. All rights reserved.
  • TCP/IP Command Referenceизсостава OS/2 (файл tcpcr.hlp)
    (C)Copyright International Business Machines Corporation 1996, 1997. All rights reserved.
  • TCP/IP Version 4.21 Programming Referenceизсостава OS/2 Warp Toolkit (файл tcppr.inf)
    (C)Copyright International Business Machines Corporation 1997, 1998. All rights reserved.
  • [RFC959] J.Postel and J.Reynolds, "File Transfer Protocol (FTP)", STD 9, RFC 959, October 1985.
  • [RFC3659] P.Hethmon, "Extensions to FTP", RFC 3659, March 2007

Прочее:

  • IBM - International Business Machines Corporation
  • OS/2 - торговая марка IBM Corp.
  • eComStation - торговаямарка Serenity Systems International