An FTP client allows lower-level access to the FTP protocol than the FTP agent provides. The RWIFtpClient class is for the advanced user who requires complete control over the protocol.
The following example program demonstrates how to use some of the basic FTP commands provided by class RWIFtpClient, such as USER, PASS, LIST, CWD, PWD, and RETR. A connection must be established initially between a client and an FTP server of interest. Then the USER/PASS protocol command sequence must be performed before most other commands can be issued. If any command is conducted out of order, an exception is thrown.
Here is a portion of code followed by comments explaining key lines.
// global variable client RWIFtpClient client; // 1
RWBoolean ftpConnect(const RWCString& machine) { ... reply = client.connect(machine); // 2 ... }
RWBoolean ftpUser(const RWCString& user) { ... RWIFtpReply reply = client.user(user); // 3 ... } RWBoolean ftpPass(const RWCString& pass) { ... RWIFtpReply reply = client.pass(pass); // 4 ... } RWBoolean ftpList(const RWCString& dir) { try { RWIFtpDataReply dataReply = client.list(dir); // 5 cout << dataReply << endl; if (!dataReply.is1XX()) return FALSE; // 6 RWCString line; RWPortalIStream strm(dataReply.portal()); // 7 while (l) line.readline(strm); // 8 if (line.isNull()) break; // 9 cout << line <<endl; } RWIFtpReply reply = client.dataClose(); //10 cout << reply << endl; if (!reply.is2XX()) return FALSE; //11 } catch (const RWxmsg& m) { //12 cout << m.why() << endl; return FALSE; } return TRUE; }
//1 | Constructs an RWIFtpClient object. The object is set to an unconnected state. The connect() method of RWIFtpClient must be used to establish a connection with an FTP server. When the program exits, the client automatically disconnects from the server. |
//2 | Establishes a connection with an FTP server. |
//3 | Performs the USER protocol command. A successful reply from the request signifies that a PASS protocol command should then be attempted. |
//4 | Performs the PASS protocol command. |
//5 | Performs the LIST protocol command. The method returns an RWIOUResult with a redeemable RWIFtpDataReply that is redeemed immediately as the dataReply object. |
//6 | Checks whether the reply is within the 1XX family (a 3-digit standard reply that starts with 1). A successful reply from the list() method is normally in the 1XX family, which indicates that the data connection has been opened. Here, a reply other than 1XX is treated as an unacceptable request. |
//7 | Creates an RWPortalIStream object strm built from a socket portal, which is returned as part of the dataReply object in //5, via the portal() method invocation. The object strm becomes the data (directory) source to be read off from the portal. |
//8 | Reads a line of data- directory entry-off the portal. |
//9 | Reads data from the portal until no more data is available. The number of times the loop is executed indicates the number of directory entries existing in the dir, specified as the argument of the list() method invocation of //5. |
//10 | Closes the portal contained with the dataReply object. The dataClose() method returns an RWIOUResult with a redeemable RWIFtpReply. By assigning the result of the method to the RWIFtpReply object reply, the current execution thread is blocked until the actual result becomes available. This is one way of redeeming an RWIOUResult. Notice that the dataClose() method needs to be invoked for each data transfer session. This is because the FTP protocol creates a data connection for each data transfer session that must be removed afterwards. |
//11 | Checks whether the reply is within the 2XX family (a 3-digit reply that starts with 2). A successful reply from the dataClose() method is normally in the 2XX family, which indicates that the underlying data channel has been closed for the LIST data transfer session. Here, a reply other than 2XX is treated as an unacceptable request. |
//12 | This catch clause catches all the int library, the net library, and Threads.h++ exceptions that could be thrown from within the try block, since all Rogue Wave exceptions are derived from RWxmsg. |
In this example, the return values of all FTP command requests that return RWIOUResults with a redeemable RWIFtpReply (or its derived class) are assigned to an object of RWIFtpReply. This indicates that the current thread is blocked until the actual result of the reply becomes available. In other words, the redeemable is redeemed immediately by blocking the thread. This is one way of redeeming an RWIOUResult object. Please refer to Section 20.4 and to Chapter 19 for other ways of redeeming an RWIOUResult.
In //5, the default data connection direction is applied. There are three different ways to specify data connection direction. See Chapter 21 for further information. Keep in mind that the direction of data connection is not related to the direction of data transfer. It is purely a connection construction issue.
©Copyright 2000, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.