Link to home
Start Free TrialLog in
Avatar of playernovis
playernovis

asked on

FTP error

Hello,

I'm trying to write my little FTP client (part of my bigger project). I'm getting this error and I have no idea what's wrong...

I always get error when I try to issue a command "LIST", any idea why?

note: I can use FTP command and log to the server without any problems.... I just want to write my own FTP....

here is what I type and the reply from the server....


TELNET server1 21
220 server1 FTP server (Authorized Use Only) ready.
USER jiri
331 Password required for jiri.
PASS mypassword
230 User jiri logged in.
TYPE A
200 Type set to A.
CDW /work1
500 'CDW /work1': command not understood.
CWD /work1
250 CWD command successful.
LIST
425 Can't build data connection: Connection refused.




ASKER CERTIFIED SOLUTION
Avatar of CoolBreeze
CoolBreeze

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of aindelicato
aindelicato

try issuing the LS command instead.. any errors ?
this is ftp, I don't think there is such a command called LS, at least according to the RFC. It is probably an alias for LIST in the ftp program you are using.
i know its FTP.

Open a CMD prompt in windows... type FTP
then OPEN ftpserver.com
login
type LS and you get a DIR list.

LS is the Directory listing command for the FTP Protocol.  What the user above is doing is TELNET, where the LIST command applies.

But why write your client to telnet into the server instead of using FTP ??

ftp maintains two connections between the server and the client. one for the control connection, one for the data connection.
the control connection follows the telnet protocol which is why he is telnet-ing into the ftp server.

the ftp protocol gives a list of ftp commands that a ftp server should accept, which includes (but not limited to) :

user, pass, acct, cwd, cdup, smnt, rein, quit, port, pasv, type, stru, mode, retr, stor, stou, appe, allo, rest, rnfr,
rnto, abor, dele, rmd, mkd, pwd, list, nlist, site, syst, stat, help, noop

note that a ftp server might not implement all the above commands.

LS is the directory listing command for your ftp client. LIST is the ftp command.

he needs to write his own ftp client, which means he has to implement his client to be able to handle some if not all the above mentioned commands. The problem he faces probably arises because he did not maintain the second connection required i.e. the data connection.

yes, it is possible to make use of another ftp client for his ftp-ing purposes, but that is probably not as efficient (since it depends on an external program instead of some internal code) and also create a dependency on the ftp client which might not be available in the target client platform, or it varies between platforms.

furthermore, if the product is supposed to be a ftp client, it sort of defeats the purpose if it relies on some other ftp client.
the LS is server based.  W2K ftp from command prompt to a servu ftp server on a win98 computer will us the LS command which does not reside on w2k or w98.  FTP being widely used on a linux system LS has been incorparated into the server.   If fact in the above scenerio 'list' returns an unkown command.

why telnet to a box when you can FTP directly.. if you telnet.. you are opening a command prompt on the remote box.. and the FTP to itself?  

not sure I follow the logic on this one.  now if you are telneting to say , a cisco router, and then ftp to a site to download a config.. that is a different scenerio...
How do you wish to use your app?

if not in a remote access.. go for FTP alone and try the LS to list the directory.
the LS is server based.  W2K ftp from command prompt to a servu ftp server on a win98 computer will us the LS command which does not reside on w2k or w98.  FTP being widely used on a linux system LS has been incorparated into the server.   If fact in the above scenerio 'list' returns an unkown command.

why telnet to a box when you can FTP directly.. if you telnet.. you are opening a command prompt on the remote box.. and the FTP to itself?  

not sure I follow the logic on this one.  now if you are telneting to say , a cisco router, and then ftp to a site to download a config.. that is a different scenerio...
How do you wish to use your app?

if not in a remote access.. go for FTP alone and try the LS to list the directory.
sorry not sure why it double submitted.
to test the above.. try this on your ftp server.. from a seperate w2k computer..
in the run command enter 'CMD"
then at the prompt enter ftp <server name or ip>
the following is a capture from such a test
the only thing edited is the user name....
the FTP Server is SERV-U

Microsoft Windows 2000 [Version 5.00.2195]
(C) Copyright 1985-2000 Microsoft Corp.

H:\>ftp 100.100.100.50
Connected to 100.100.100.50.
220 Serv-U FTP Server v5.0 for WinSock ready...
User (100.100.100.50:(none)): <user name>
331 User name okay, need password.
Password:
230 User logged in, proceed.
ftp> ls
200 PORT Command successful.
150 Opening ASCII mode data connection for /bin/ls.
AUTOEXEC.BAT
BOOTLOG.PRV
BOOTLOG.TXT
COMMAND.COM
CONFIG.SYS
DBLSPACE.BIN
DBLSPACE.INI
DETLOG.OLD
DETLOG.TXT
DRVSPACE.BIN
IO.SYS
MSDOS.---
MSDOS.SYS
NETLOG.TXT
NTFSDOS.EXE
SCANDISK.LOG
SETUPLOG.TXT
SETUPXLG.TXT
SUHDLOG.DAT
SYSTEM.1ST
VIDEOROM.BIN
WINSTALL.DMP
WINSTALL.LOG
ftplog.txt
wrdrv.log
226 Transfer complete.
ftp: 318 bytes received in 0.13Seconds 2.43Kbytes/sec.
ftp> quit
221 Goodbye!

H:\>


>> W2K ftp from command prompt to a servu ftp server on a win98 computer will us the LS command which does not reside on w2k or w98.

do you meant "which does not reside on w2k" ? because I'm quite puzzled by the "win98 computer" and "does not reside on w98".

>> FTP being widely used on a linux system LS has been incorparated into the server.

I just tried on a unix/linux system, and it says it is an unknown command. LIST works okay here.

>> why telnet to a box when you can FTP directly.. if you telnet.. you are opening a command prompt on the remote box.. and the FTP to itself?  

note my above explanations (the post before yours), in ftp session, two connections are made - one called the control connection which effectively is a telnet session (usually) and the other a data connection. In telnet-ing, he is actually
establishing this control connection.

>> if not in a remote access.. go for FTP alone and try the LS to list the directory.

note the difference between a FTP CLIENT and the FTP PROTOCOL. the RFC 959's title is File Transfer Protocol, which is
effectively FTP, but we usually call it FTP PROTOCOL anyway. The FTP CLIENT can provide its own versions of commands,
but effectively it is still has to send the commands specified by the FTP PROTOCOL to the server in its communication. That is to say, I can implement a FTP CLIENT with the command TELL_ME_THE_FILES, which I actually translate it into LIST before sending it to the server. SO the LS command you are talking about (sounds to me) is the command implemented by the FTP CLIENT, not the PROTOCOL. Just like my TELL_ME_THE_FILES command.

If I am not wrong, he is looking for FTP PROTOCOL not FTP CLIENT, as evident from his words:

"I'm trying to write my little FTP client"

which sounds to me that he is highly unlikely to make his FTP CLIENT to call another FTP CLIENT just to implement his FTP CLIENT.
to add on, from my interpretation, he is not trying to find out how to use a ftp client, he is trying to write one. he is not trying to use ftp.exe, he is trying to write one similar to it.
OPEN SOURCE CODE OF A SIMPLE FTP CLIENT

FTP RESOURCES -- http://war.jgaa.com/ftp/?cmd=about

MORE SAMPLE SOURCE CODE: http://war.jgaa.com/ftp/?cmd=src


See how yours compares.






/* dftp: FTP client example
 * Copyright (c) 1996 by Donald C. Asonye
 * Email: donald@uh.edu
 *
 * commands.c.
 *
 * This and other files are hereby released      to the public for
 * educational purposes.  You may redistribute this and other files
 * or routines as long as you are not compensated for it, and as
 * long as this notice is included with it.  You may not use the
 * released source codes in anyway commercial without permission.
 *
 * It'd be nice if you share your modifications with me and everyone
 * else.  I encourage you to make the code better as I am very busy.
 *
 * Share your knowledge :)
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "commands.h"
#include "extfuncs.h"

char szBuffer[1025]={0};  /* buffer used to read/write */
char szUser[20];          /* stores username */
char szPass[256];         /* stores user password */
extern int Connected;     /* flag for connect status */


/*
 * CheckCommand
 * this is the main command parser.  it scans user input
 * and returns the correct command flag.  it's fairly
 * straight forward.  just a bunch of strcmp & strncmp
 */
int CheckCommand(char *command)
{
   
    if( !strcmp(command,"pwd") )
      return PWD;
    if( !strncmp(command,"rhelp",5) )
      return RHELP;
    if( !strncmp(command,"help",4) )
      return HELP;
    if( !strncmp(command,"ls ",3) || !strcmp(command,"ls")
      || !strcmp(command,"dir"))
      return LS;
    if( !strcmp(command,"cd") || !strncmp(command,"cd ",3) )
      return CD;
    if( !strcmp(command,"close"))
      return CLOSE;
    if( !strcmp(command,"quit") || !strcmp(command,"bye") ||
      !strcmp(command,"exit") )
      return QUIT;
    if( !strcmp(command,"open") || !strcmp(command,"o") ||
      !strncmp(command,"open ",5) || !strncmp(command,"o ",2) )
      return OPEN;
    if( !strcmp(command,"lls") || !strcmp(command,"ldir") )
      return LLS;
    if( !strcmp(command,"lcd") || !strncmp(command, "lcd ",4) )
      return LCD;
    if( !strcmp(command,"user") || !strncmp(command,"user ",5))
      return USER;
    if( !strcmp(command,"bin") || !strcmp(command,"binary") )
      return BINARY;
    if( !strcmp(command,"as") || !strcmp(command,"ascii") )
      return ASCII;
    if( !strncmp(command,"!",1) )
      return SHELL;
    if( !strncmp(command,"get ", 4) )
      return GET;
    if( !strncmp(command,"put ", 4) )
      return PUT;

    return -1;   /* unsupported command */
}

/*
 * DoOpen
 * this function is called when the o,open command is issued.
 * it connects to the requested host, and logs the user in
 *
 */
void DoOpen( char *command)
{
  char *szHost=NULL;  /* remote host */

   /*
    * do not do anything if we are already connected.
    */
   if( Connected ) {
       printf("Already connected.  Close connection first.\n");
       fflush(stdout);
       return;
   }
   
   /*
    * extract the remote host from command line (if given ).
    * make a copy of the host name with strdup.
    */
   if(!strcmp(command,"open") || !strcmp(command,"o")) {

       printf("Host:"); fgets(szBuffer,1024,stdin);
       (void)strtok(szBuffer,"\n");
       szHost = (char *)strdup(szBuffer);;
   }
   else if( !strncmp(command,"open ",5))
      szHost = strdup(&command[5]);
   else if( !strncmp(command,"o ",2) )
      szHost = strdup(&command[2]);
   else
      szHost = strdup(command);


   printf("Connecting to %s\n",szHost);
   hControlSocket = ConnectToServer(szHost,"21");

#if (defined(WIN32) || defined(_WIN32) )
   Sleep(1);
#else
   sleep(1);
#endif

   if( hControlSocket > 0)  {
     printf("Connected to %s\n",szHost);
#if (defined(WIN32) || defined(_WIN32) )
   
       sprintf(command,"dftp: Connected to %s ", szHost);

       SetConsoleTitle(command);  /* set console window title */
#endif

     Connected = 1;         /* we ar now connected */
     GetReply();            /* get reply (welcome message) from server */
     DoLogin((char *)NULL); /* prompt for username and password */
     DoBinary();            /* default binary mode */
   }
   free(szHost); /* free the strdupped string */
}

/*
 * DoLogin
 * this function logs the user into the remote host.
 * prompts for username and password
 */
void DoLogin( char *command)
{
 char *User=NULL;
 
  if( command && *command)
     User=&command[5];

   if( Connected )  {

     /*
      * ignore leading whitespace
      */
     while(User && (*User == ' ' || *User == '\t') && *User)
       User++;
     /*
      * if user name was not provided via command line, read it in.
      */
     if(!User || !(*User) ) {
      printf("Login:"); fgets(szUser,20,stdin);
      User = szUser;
      (void)strtok(szUser,"\n");   /* remove '\n' */
     }

     /*
      * send user name & password to server  & get reply message
      */
     sprintf(szBuffer,"USER %s\r\n",User);
     SendControlMsg(szBuffer,strlen(szBuffer));
     GetReply();
     GetPassword( szPass );

     sprintf(szBuffer,"PASS %s\r\n",szPass);
     SendControlMsg(szBuffer,strlen(szBuffer));
     GetReply();
   }
   else
      printf("Not Connected.\n");
}

/*
 * DoClose
 * closes connection to the ftp server
 */
void DoClose( void )
{
   if( !Connected  ) {
     printf("Not Connected.\n");
   
   }
   else {
         SendControlMsg("quit\r\n",6);
         GetReply();
         CloseControlConnection();
         hControlSocket = -1;
#if (defined(WIN32) || defined(_WIN32) )
   
         SetConsoleTitle("dftp: Connection closed");
#endif

         Connected = 0;
   }

}

/*
 * DoList
 * perform directory listing i.e: ls
 */
void DoList( char *command)
{
   if( !Connected ) {
      printf("Not Connected.\n");
      return;
   }

   /*
    * obtain a listening socket
    */
   if( GetListenSocket() < 0) {
       printf("Cannot obtain a listen socket.\n");
       return;
   }
   
   /*
    * parse command
    */
   if( !strcmp(command,"ls") )  {
       sprintf(szBuffer,"NLST\r\n");
   }
   else if( !strcmp(command,"dir") )
       sprintf(szBuffer,"LIST\r\n");

   else if( !strncmp(command, "ls ",3)) {
       while( *command == ' ') command++;
       sprintf(szBuffer,"LIST %s\r\n",&command[3]);
   }
   /*
    * send command to server and get response
    */
   SendControlMsg(szBuffer,strlen(szBuffer));
   memset(szBuffer,0,1024);
   GetReply();

   /*
    * accept server's connection
    */
   if(AcceptConnection() < 0) {
      printf("Cannot accept connection.\n");
      return;
   }
   CloseListenSocket();       /* close listening socket */

   /*
    * display directory listing.
    */
   while( ReadDataMsg(szBuffer,1024) > 0) {
       fflush(stdout);
       printf(szBuffer);
       memset(szBuffer,0,1024);
   }
   /*
    * read response
    */
   (void)GetReply();

}

/*
 * DoCD
 * chang to another directory on the remote system
 */
void DoCD( char *command)
{
   char *dir=&command[2];

   if( !Connected ) {
       printf("Not Connected.\n");
       return;
   }

   /*
    * ignore leading whitespace
    */
   while( *dir && (*dir == ' ' || *dir == '\t') )
       dir++;

   /*
    * if dir is not specified, read it in
    */
   if( ! (*dir) ) {
      printf("Remote directory:");
      fgets(szBuffer,1024,stdin);
      (void)strtok(szBuffer,"\n");
      dir = (char *)strdup(szBuffer);
      while( *dir && (*dir) == ' ')
       dir++;
      if( !(*dir) ) {
      printf("Usage: cd remote-directory\n");
      return;
      }
   }
   
   /*
    * send command to server and read response
    */
   sprintf(szBuffer, "CWD %s\r\n",dir);
   SendControlMsg(szBuffer,strlen(szBuffer));
   (void)GetReply();
}

/*
 * DoLCD
 * change directory on the local system
 */
void DoLCD( char *command)
{

   char *dir = &command[3];

   while(*dir && (*dir == ' ' || *dir == '\t') ) dir++;

   /*
    * if dir is not specified, then print the current dir
    */
   if( ! *dir ) {
      dir = getcwd((char *)NULL,256);
      if( !dir)
      perror("getcwd");
      else
      printf("Current directory is: %s\n",dir);
   }
   else {
      if( chdir(dir) < 0)
      perror("chdir");
      else {
      dir = getcwd((char *)NULL,256);
      if( !dir)
          perror("getcwd");
      else
      printf("Current directory is: %s\n",dir);
      }
   }
}

/*
 * DoLLS
 * perform local directory listing.  winqvt implements this, but
 * this is not supported by many systems.  it's not really needed
 * since we already have '!' command.  you can just do !ls or !dir.
 */
void DoLLS( char *command )
{
#if ( !defined(_WIN32) || !defined(WIN32) )
    system("ls");
#else
    system("dir");
#endif
}

/*
 * function to pass commands to the system, ie: dir.
 * this function gets called when '!' is encountered
 */
void DoShellCommand( char *command )
{
  command++;  /* ignore '!' */
#if ( !defined(_WIN32) || !defined(WIN32) )

    system(command);
#else
      if( !command || !*command)
            system("cmd");   /* have to fix this for win95 */
      else                     /* maybe i should use 'start' */
            system(command); /* programatically determine which */
#endif                           /* system we are on, then make the  */
                         /* appropriate call */
}


/*
 * DoBinary
 * set file transfer mode to binary
 */
void DoBinary()
{
  if( !Connected ) {
      printf("Not Connected.\n");
      return;
  }
   sprintf(szBuffer, "TYPE I\r\n");
   SendControlMsg(szBuffer,strlen(szBuffer));
   GetReply();
   printf("File transfer modes set to binary.\n");
   bMode = BINARY;
}

/*
 * DoAscii
 * set file transfer mode to ascii text
 */
void DoAscii()
{
  if( !Connected ) {
      printf("Not Connected.\n");
      return;
  }
   sprintf(szBuffer, "TYPE A\r\n");
   SendControlMsg(szBuffer,strlen(szBuffer));
   GetReply();
   printf("File transfer modes set to ascii.\n");
   bMode = ASCII;

}

/*
 * DoGet
 * retrieve a file from the remote host.  calls GetFile(..)
 */
void DoGet( char *command)
{

  if( !Connected ) {
      printf("Not Connected.\n");
      return;
  }
  (void)strtok(command," ");
  GetFile(strtok((char *)NULL, " "));
}

/*
 * DoPut
 * send a file to the remote host.  calls PutFile(..)
 */
void DoPut( char *command )
{
  if( !Connected ) {
      printf("Not Connected.\n");
      return;
  }
  (void)strtok(command," ");
  PutFile(strtok((char *)NULL, " "));
}

/*
 * DoRhelp
 * sends a help command to the server.
 */
void DoRhelp( char *command )
{
  char *szCommand;

  if( !Connected ) {
      printf("Not Connected.\n");
      return;
  }
  (void)strtok(command," ");
  szCommand=strtok((char *)NULL, " ");

  if( szCommand && *szCommand )
     sprintf(szBuffer,"HELP %s\r\n",szCommand);
  else
     sprintf(szBuffer, "HELP\r\n");
 
  SendControlMsg(szBuffer, strlen(szBuffer));
  GetReply();
}

/*
 * retrieves the current directory on the remote host
 */
void DoPWD()
{

  if( !Connected ) {
      printf("Not Connected.\n");
      return;
  }
  sprintf(szBuffer, "PWD\r\n");
  SendControlMsg(szBuffer,strlen(szBuffer));
  GetReply();
}
BTW ...I dont see anywhere in this code where the author uses TELNET to create a CONTROL CONNECTION.  He uses the OPEN command commonly used in both UNIX and WIN.
The author provides the command OPEN in his ftp client, not he uses it.
The author opens a connection with the server, and talk to it using the TELNET PROTOCOL. This connection is called a CONTROL CONNECTION. This is effectively the same as us using the TELNET PROGRAM to connect to the server (only now that it is done within this program).
Here is a print of the ftp I just did to a linux box
agian the only thing I edited was the username
what I meant by does not reside on the win98 or win2K is that if you type LS at a command prompt it will not work
not sure why or it is not working in the scenerio you tryed as it is a base linux command.
check this site for more information.
http://www.cs.colostate.edu/helpdocs/ftp.html
I understand he is writing his own client..... but he will have to use the commands that the ftp servers reconize...
once you establish an FTP connection via the FTP protocol  you must use FTP commands the server will be able to interpret..


Microsoft Windows 2000 [Version 5.00.2195]
(C) Copyright 1985-2000 Microsoft Corp.

H:\>ftp 10.57.220.110
Connected to 10.57.220.110.
220 coxty FTP server (Version wu-2.6.2-5) ready.
User (10.57.220.110:(none)): ,username
331 Password required for username
Password:
230 User username logged in.
ftp> ls
200 PORT command successful.
150 Opening ASCII mode data connection for file list.
atomsmgr
atomsmgr.bak
char_drsplay
char_simulate
char_tidcbqa
char_tsrlogin
char_vmplay
dcbbuild
dcbmanappt
dcbqamgr
dcm_launch
drsplay
phone.txt
phonedis.txt
psmgrlogin
psreclogin
simulate
tidcbqa
tsrlogin
vmplay
226 Transfer complete.
ftp: 234 bytes received in 0.00Seconds 234000.00Kbytes/sec.
ftp> quit
221-You have transferred 0 bytes in 0 files.
221-Total traffic for this session was 550 bytes in 1 transfers.
221-Thank you for using the FTP service on coxty.
221 Goodbye.

H:\>
thanks, Tele_tech.
I guess we just have different views regarding what is a ftp command. Your definition of a ftp command is the command you enter in a ftp client. In this case, ls. My definition of ftp command (in the context of this question) is the actual command sent to the ftp server. In this case, NLST (or LIST).

Notice in the code you provided, under the function

void DoList( char *command);

which according to the comments, do a ls.
now notice this statement inside the function:

   if( !strcmp(command,"ls") )  {
       sprintf(szBuffer,"NLST\r\n");
   }

which actually stores in a buffer the command "NLST", and this code (also inside the function):

SendControlMsg(szBuffer,strlen(szBuffer));

sends what is inside the buffer to the server (i.e. "NLST"). In other words, what the server actually sees is "NLST"
(or in some implementations, "LIST")
and to add on, that is the command that the server recognizes.
ls is the command that the client recognizes.

if you do not agree, perhaps you can suggest a way to write a ftp client by sending in the command "ls" and it works.
I reviewed the code and see what you are saying... (BTW code submitted by: aindelicato)

interesting... well sometimes even those trying to assist pick up a tidbit... :)  enjoy

out of curiosity.. what version unix/ Linux did you get the unknown command on?  

In telnet and ftp as well as on the console.. i have always used ls... and the one I have here at the office... list is unknown and yet ls and dir are both know....
from your description  maybe I ought to ask.. what client you are using?

oops, yeah the code was submitted by adindelicato :)

what I'm talking about (the ftp commands) is those commands that are sent by the client to the server (internally, i.e. we don't get to see it). The commands we use are still "ls" at the client side (this is what we enter into the client, not what is sent to the server, ls is probably for historical reasons, i.e. unix). What the client do (no matter which client), is to translate this command (i.e. "ls") into the command "NLST" (or sometimes "LIST").

so in other words, no matter what client or server you use (of course they must be compliant with the standards), what is sent by the client to the server is always "NLST" (or sometimes "LIST") regardless of the commands that the client provide.

There are two classes of ftp commands here.
- Ftp commands on the client, which is what you enter in your ftp client.
- Ftp commands which are sent from the client to the server

Note that the commands in both classes need not be the same (in this case, ls is a client ftp command while LIST is the second class of ftp command). The first class of ftp commands is non-standard and people are free to implement them however they want. That is to say, while one client, you use "ls" to see the listing, on another client, you might have to
use "show_me_the_files" to see the listing.

The second class of ftp commands is however standardized. And it is defined in RFC 959 (http://www.faqs.org/rfcs/rfc959.html) and subsequent related RFCs. There is a standard list of commands (and
some optional ones) that a compliant server and client have to adhere to.

In general usage of ftp, we usually refer to the first class of ftp commands. However in programming, usually the first
class of ftp commands have not much relevance, and we usually refers to the second class of ftp commands.

Which is why the ftp client you use, LIST is unknown, because it belongs to the second class of ftp commands.

A plain (normal) Telnet session is different from the control connection you make in a ftp session, in that a telnet session
usually puts you in the shell of the system. And since the system you telnet to is unix/linux based, you uses the ls command.
However, you can try Telnet-ing to a ftp server at port 21. There you will see ls does not actually works (because that
belongs to the first class of ftp commands and is not what is actually communicated to the server). Try the following list of
commands (brackets are comments):

telnet 10.57.220.110 21
[in the telnet now]
user username
[user authenicated, asking for password]
pass password
[password authenicated, authorized]
ls
[will show error, unknown command]
pwd
[tells you the current working directory]
quit
[ends the session]

this will gives you a glimpse of what actually happen internally between a ftp client and the server.
CoolBreeze..  Thank you,
As I said in earlier post.. sometimes we who attempt to help.. pick up a tidbit..
Good Call...  

    I stand down
Avatar of playernovis

ASKER

CoolBreeze, your first comment solved my problem, thanks a lot. I forgot that FTP is not as straight as telnet or http protocols....


for all of you who do not understand why I need it....   ORACLE has package called UTL_TCP. It is very low level communication package. I can use it and write my own FTP client, my own TELNEt client, my own HTTP client and get and send raw data from PLSQL (no external calls, no special C++ libraries....).


jiri