developer.com - Reference
Click here to support our advertisers
SHOPPING
JOB BANK
CLASSIFIEDS
DIRECTORIES
REFERENCE
Online Library
LEARNING CENTER
JOURNAL
NEWS CENTRAL
DOWNLOADS
COMMUNITY
CALENDAR
ABOUT US
Journal:
Get the weekly email highlights from the most popular journal for developers!
Current issue
developer.com
developerdirect.com
htmlgoodies.com
javagoodies.com
jars.com
intranetjournal.com
javascripts.com
All Categories :
Java
Chapter 26
Client Programs
CONTENTS
Types of Clients
Client Responsibilities
A Simple Telnet Client
The Network Virtual Terminal
The Interpret as Command Code
Negotiated Options
Symmetry Between Terminals and Processes
The TelnetApp Program
The NVTPrinter Class
The NVTInputStream Class
The NVTOutputStream Class
A Mail Client
The MailClientApp Program
The Web Fetcher Program
Summary
In this chapter you will learn how to write
client programs that support networked client/server applications.
You'll learn about the typical client programs found on the Internet
and how they are structured. You'll develop simple client programs
that support remote login and the sending of mail, and that fetch
a list of Web pages. This chapter builds on the material presented
in Chapter 17, "Network Programming
with the java.net
Package." You might want to review Chapter 17 before
continuing with the material presented in this chapter.
Types
of Clients
Of the client/server applications that are found on the Internet,
only a small group is typically used. These include e-mail, the
Web, FTP, Usenet news groups, and telnet. Gopher and WAIS, both
precursors of the Web, have declined in popularity, having been
subsumed by the Web. Typical Internet client programs include
e-mail programs, Web browsers, FTP programs, and telnet clients.
E-mail programs provide an easy-to-use interface by which
mail can be created and sent, retrieved and displayed, and managed.
Popular window-based clients include Eudora and Pegasus. UNIX
systems provide a number of popular e-mail clients, including
Pine, Elm, and mh.
Web browsers provide a window on the World Wide Web and
support the display of Web pages, including, of course, Java programs.
The Netscape browser is the most popular browser on the Web and
is Java capable. It is supported on UNIX, Windows, and Macintosh
systems.
FTP programs provide a convenient way to retrieve files
from public Internet file servers or from private file directories.
Although a number of user-friendly FTP client programs are available,
the simple text-based FTP client is still the most popular and
most widely supported.
Newsreader programs simplify the process of working with messages
that are posted to Usenet news groups. A number of netnews client
programs are available for Windows, Macintosh, UNIX, and other
operating system platforms.
Telnet clients are used to remotely log into other systems. These
systems are usually UNIX or other operating systems that are powerful
enough to provide the underlying capabilities needed to implement
multiuser support. Windows and Macintosh systems, because of their
inherent limitations, do not support telnet server applications.
Client
Responsibilities
Client programs perform a service for their users by connecting
with their server counterparts, forwarding service requests based
on user inputs, and providing the service results back to the
user.
In most cases, the client must initiate the connection. Typically,
the server listens on a well-known port for a client connection.
The client initiates the connection, which is accepted by the
server. The client sends a service request to the server, based
on user inputs. The server receives the service request, performs
the service, and returns the results of the service to the client.
The client receives the service results and displays them to the
user.
A
Simple Telnet Client
A telnet client program provides users with the capability to
log into remote systems. It connects to a telnet server (called
a telnet daemon) that listens on port 23 for an incoming
connection. The telnet client connects to the daemon, which usually
runs a login program and, upon successful login, runs a shell
program.
The telnet client must be capable of simultaneously exchanging
data with both the user and the remote system. The protocol used
for communication between the client and the server is specified
in RFC 854, the Telnet Protocol Specification. RFC 854 identifies
three basic elements of the telnet protocol: the concept of a
network virtual terminal, the principle of negotiated options,
and the symmetry between terminals and processes.
The Network Virtual Terminal
The network virtual terminal, or NVT, is a very simple
device that forms the basis for establishing telnet-based communication.
All telnet clients and servers are required to support the NVT
as a minimum capability. It is an abstract device that consists
of a printer and a keyboard. The user types characters on the
keyboard that are forwarded to the server. The server returns
data to the user and the NVT displays it on the printer. The NVT
provides local character echoing and half-duplex operation, although
remote echoing and full-duplex operation can be used as negotiated
options. Lines are terminated using a standard carriage-return-line-feed
combination.
The NVT also provides for control operations that support process
interruption and the discarding of excessive output. These operations
are signaled by using the Interpret as Command (IAC) code
as described in the next section.
The Interpret as Command
Code
The IAC code is sent from a client or server to a program on the
other end of a telnet connection to send a control code or to
negotiate an option, as described in the next section. The IAC
is a single byte consisting of the value 255
or hex 0xFF. The IAC may
be followed by a single byte to send a control code, or by two
or more bytes to negotiate an option. For example, the IAC followed
by a byte with the decimal value of 243 is used to send a break
command.
Because the IAC is used to indicate a command or option negotiated,
a special byte sequence is needed to send the byte value 255 used
for the IAC. This is accomplished by sending two IACs in succession.
Negotiated Options
Because all telnet clients and servers are required to implement
the NVT, they all have a common, but primitive, basis from which
to begin operation. Additional options, such as full- duplex operation
and character echoing, can be used based on the principle of negotiated
options.
Options are negotiated when either the client or server
program sends an IAC code to the other. The IAC code is followed
by a WILL or DO
code and an option code. The WILL
code informs the program on the other side of the connection that
it intends to use a particular option. The other program may respond
with a DO or a DONT
response, consisting of the IAC, followed by the DO
or DONT code, followed by
the option.
A program can also request that the program on the other side
of the connection implement an option. This is accomplished by
sending the IAC code, the DO
code, and the option code. The other program can respond with
a WILL or WONT
response. A WILL response
is indicated by sending the IAC, followed by the WILL
code, followed by the option code. A WONT
response is sent in the same manner, with the WONT
code being used instead of the WILL
code.
Symmetry Between
Terminals and Processes
As you probably have surmised from reading the previous sections,
the communication between client and server is highly symmetrical.
Either the client or server can initiate option negotiation. The
use of symmetry between client and host simplifies the implementation
of the telnet protocol and allows client and host software to
be developed from a common base. The TelnetApp
program, presented in the next section, makes use of two I/O filters,
NVTInputStream and NVTOutputStream,
that implement some of the basic elements of the telnet protocol.
These streams do not support control characters or additional
options. Option negotiation is handled by refusing any additional
options other than those provided by the basic NVT.
The TelnetApp
Program
The TelnetApp program implements
a minimum set of features of the telnet protocol in order to accomplish
a remote login to a telnet server. The purpose of the program
is not to provide you with a telnet client, but to show you the
basics of how these clients work. More sophisticated and powerful
telnet client programs can be retrieved from the Internet. The
source code of the TelnetApp
program is shown in Listing 26.1.
Listing 26.1. The source code for the TelnetApp
program.
import java.lang.*;
import java.net.*;
import java.io.*;
import jdg.ch26.NVTInputStream;
import jdg.ch26.NVTOutputStream;
import jdg.ch26.NVTPrinter;
public class TelnetApp {
public static void main(String args[]){
PortTalk portTalk = new PortTalk(args);
portTalk.start();
}
}
class PortTalk extends Thread {
Socket connection;
PrintStream outStream;
NVTInputStream inStream;
NVTPrinter printer;
public PortTalk(String args[]){
if(args.length!=2) error("Usage:
java TelnetApp host port");
String destination = args[0];
int port = 0;
try {
port = Integer.valueOf(args[1]).intValue();
}catch (NumberFormatException ex) { error("Invalid
port number"); }
try{
connection = new Socket(destination,port);
}catch (UnknownHostException ex) { error("Unknown
host"); }
catch (IOException ex) { error("IO
error creating socket"); }
try{
outStream = new PrintStream(connection.getOutputStream());
inStream = new NVTInputStream(connection.getInputStream(),outStream);
}catch (IOException ex) { error("IO
error getting streams"); }
System.out.println("Connected to
"+destination+" at port "+port+".");
}
public void run() {
printer = new NVTPrinter(inStream);
printer.start();
yield();
processUserInput();
shutdown();
}
public void processUserInput() {
try {
String line;
boolean finished = false;
DataInputStream userInputStream
= new DataInputStream(System.in);
do {
line = userInputStream.readLine();
if(line == null) finished
= true;
else outStream.println(line);
} while(!finished);
} catch(IOException ex) {
error("Error reading user input");
}
}
public void shutdown(){
try{
connection.close();
}catch (IOException ex) { error("IO error
closing socket"); }
}
public void error(String s){
System.out.println(s);
System.exit(1);
}
}
Note
The TelnetApp class uses the NVTPrinter, NVTInputStream, and NVTOutputStream classes that are supplied in the following sections. You must type in the NVTPrinter.java, NVTInputStream.java, and NVTOutputStream.java files before compiling TelnetApp.java. The Java compiler will automatically compile these files when TelnetApp.java is compiled.
You use the TelnetApp program
in the same way as any other telnet program. But bear in mind
that it is only a minimal telnet client. Run the program by invoking
it with the hostname of a computer that supports telnet and the
well-known telnet port number, port 23.
In the following example, I use the program to log into my account
at CTS. Note that the program operates in half-duplex mode, so
characters are echoed locally. I substituted asterisks (*)
for my password. Take caution when using this program because
it will display your password characters in the same manner as
any other text that you type.
Also, notice that commands that I type are echoed by my cts.com
host:
C:\java\jdg\ch26>java TelnetApp cts.com
23
Connected to cts.com at port 23.
UNIX System V Release 3.2 (crash.cts.com) (ttyp2)
login: jaworski
Password:****
Last successful login for jaworski: Tue Apr 09 23:17:46 PDT 1996
on ttyp34
Last unsuccessful login for jaworski: Fri Apr 05 09:56:34 PST
1996 on ttyp9
Welcome
to CTSNET!
Enter 'help' for
assistance and information.
1% l
l
total 16
drwx------ 2 jaworski guest 272 Sep 08 1995 Mail
drwxr-xr-x 2 jaworski guest 208 Dec 07 15:09 News
drwxr-xr-x 2 jaworski guest 224 Sep 08 1995 bin
drwxr-xr-x 2 jaworski guest 384 Apr 04 08:43 download
lrwxrwxrwx 1 root root 15 Mar 15 02:56 dropbox -> /ftp/j/jaworski
drwx------ 2 jaworski guest 160 Dec 08 10:35 ga
drwx------ 2 jaworski guest 288 Apr 08 09:49 mail
drwxr-xr-x 3 jaworski guest 112 Dec 01 12:20 writing
2% exit
exit
3% logout
Connection broken.
C:\java\jdg\ch26>
The TelnetApp program creates
an object of class PortTalk
to perform its processing. This class extends the Thread
class in order to implement multithreading capabilities. Its constructor
uses the parameters passed in the TelnetApp
command-line invocation to set up the connection to the specified
host and port.
The run() method creates
an object of the NVTPrinter
class to interface with the destination host and invokes the processUserInput()
method to interface with the user. The processUserInput()
method reads a line at a time from the user's console and sends
it to the telnet server.
The NVTPrinter
Class
The NVTPrinter class performs
most of the interesting processing because it interfaces with
the server. It does this using the NVTInputStream
class covered in the next section. NVTPrinter
is also implemented as a subclass of Thread.
Its source code is shown in Listing 26.2.
Listing 26.2. The source code for the NVTPrinter
class.
package jdg.ch26;
import java.io.*;
public class NVTPrinter extends Thread {
NVTInputStream inStream;
public NVTPrinter(NVTInputStream in) {
super();
inStream = in;
}
public void run() {
boolean finished = false;
try {
do {
int i = inStream.read();
if(i == -1) finished = true;
else{
System.out.print((char) i);
System.out.flush();
yield();
}
} while(!finished);
System.out.println("\nConnection broken.");
System.exit(0);
} catch (IOException ex) {
System.out.println("NVTPrinter error");
System.exit(1);
}
}
}
The NVTInputStream
Class
The NVTInputStream class
implements the network virtual terminal input interface. Its source
code is shown in Listing 26.3.
Listing 26.3. The source code for the NVTInputStream
class.
package jdg.ch26;
import java.io.*;
public class NVTInputStream extends FilterInputStream {
byte IAC = (byte) 0xff;
byte DO = (byte) 0xfd;
byte WILL = (byte) 0xfb;
byte CR = 13;
byte LF = 10;
int WONT = 252;
int DONT = 254;
int BUFFER_SIZE = 1024;
OutputStream out;
byte lineBuffer[] = new byte[BUFFER_SIZE];
int numBytes = 0;
public NVTInputStream(InputStream inStream,OutputStream
outStream) {
super(inStream);
out = outStream;
}
public int read() throws IOException {
boolean recIAC;
int i;
do {
recIAC = false;
i = in.read();
if(i == -1) return i;
byte b = (byte) i;
if(b == IAC) {
recIAC = true;
int cmd = in.read();
if(cmd == -1) return cmd;
byte b2 = (byte) cmd;
if(b2 == IAC) return 255;
else if(b2 == DO) {
int opt = in.read();
if(opt == -1) return opt;
out.write(255);
out.write(WONT);
out.write(opt);
out.flush();
}else if(b2 == WILL) {
int opt = in.read();
if(opt == -1) return opt;
out.write(255);
out.write(DONT);
out.write(opt);
out.flush();
}
}
} while(recIAC);
return i;
}
public String readLine() throws IOException {
numBytes = 0;
boolean finished = false;
do {
int i = read();
if(i == -1) return null;
byte b = (byte) i;
if(b == LF) {
if(numBytes>0) {
if(lineBuffer[numBytes-1] == 13)
return new String(lineBuffer,0,0,numBytes-1);
}
}
lineBuffer[numBytes] = b;
++numBytes;
} while (!finished);
return null;
}
}
NVTInputStream uses the network
virtual terminal conventions, covered earlier in this chapter,
to filter the input stream associated with the connection. It
implements the basic read()
method and also a convenient readLine()
method.
The NVTOutputStream
Class
The NVTOutputStream class
provides an output analog to the NVTInputStream
class. It implements the basic write()
method according to the NVT conventions. It also provides a println()
method that uses the carriage-return-line-feed (CR-LF)
end-of-line conventions. Its source code is shown in Listing 26.4.
Listing 26.4. The source code for the NVTOutputStream
class.
package jdg.ch26;
import java.io.*;
public class NVTOutputStream extends PrintStream {
int IAC = 255;
byte CR = 13;
byte LF = 10;
public NVTOutputStream(OutputStream outStream) {
super(outStream);
}
public void write(int i) {
if(i == IAC) super.write(i);
super.write(i);
}
public void println(String s) {
super.print(s);
super.write(CR);
super.write(LF);
super.flush();
}
}
A Mail Client
Although mail is sent on the Internet using a variety of protocols,
the Simple Message Transfer Protocol (SMTP), described
in Request for Comments (RFC) 821, is the basic protocol used
to move mail from one host to another. SMTP consists of a mail
sender, a mail receiver, and a set of line-oriented commands used
to send mail from the sender to the receiver.
Note
Requests for Comments are numbered notes of the Internet community that are usually, but not always, used to describe some aspect of the protocols or services used on the Internet.
RFC 821 describes the complete set of commands used by mail senders
and receivers. Here I am using only a minimal subset of these
commands to illustrate the development of an SMTP client, the
mail sender.
An SMTP client connects to an SMTP server by establishing a connection
to port 25 of the server's host. The server accepts the connection,
sends a one-line ready notification to the client, and awaits
client commands.
The client sends the HELO
command with its hostname to introduce itself to the server. The
server responds by sending a code that indicates that it is OK
to initiate a mail transmission.
The client sends the MAIL
command to the server to indicate that it has mail from a specific
user. The server responds with a notification to proceed.
The client sends the RCPT
command to identify the recipient of the e-mail. The server responds
by telling the client whether or not the recipient is valid.
The client sends the DATA
command to indicate that it is ready to send the message. The
server responds by telling the client that it is OK to begin sending
message data.
The client sends the message, a line at a time, terminating the
message with a line containing a single period (.).
A line of message text beginning with a period is sent by prepending
an extra initial period to the message line.
The server acknowledges receiving the last line of text by sending
an OK command to the client.
The client then terminates the connection by sending a QUIT
command to the server. The server then responds by notifying the
client that it is closing the connection.
The MailClientApp
Program
The MailClientApp program
illustrates the basic operation of a mail client program. It implements
the basic SMTP commands described in the previous section. Its
source code is shown in Listing 26.5.
Listing 26.5. The source code for the MailClientApp
program.
import java.lang.*;
import java.net.*;
import java.io.*;
import java.util.Vector;
import jdg.ch26.NVTInputStream;
import jdg.ch26.NVTOutputStream;
import jdg.ch26.NVTPrinter;
public class MailClientApp {
public static void main(String args[]){
MessageInterface messageInterface = new
MessageInterface();
Message msg = messageInterface.getMsg();
MailTalk mailTalk = new MailTalk(msg);
mailTalk.run();
}
}
class Message {
String source;
String destination;
String subject;
String text[];
public Message() {
super();
}
public void setDestination(String dest) {
destination = dest;
}
public String getDestination() {
return destination;
}
public void setSource(String src) {
source = src;
}
public String getSource() {
return source;
}
public String getDestinationHost() {
return destination.substring(destination.indexOf('@')+1);
}
public void setSubject(String subj) {
subject = subj;
}
public String getSubject() {
return subject;
}
public void setText(Vector txt) {
int n = txt.size();
text = new String[n];
for(int i = 0; i< n; ++i) {
text[i] = (String) txt.elementAt(i);
}
}
public String[] getText() {
return text;
}
}
class MessageInterface {
Message msg;
public MessageInterface() {
msg = new Message();
}
public Message getMsg() {
try {
System.out.print("From: ");
System.out.flush();
DataInputStream inStream = new DataInputStream(System.in);
msg.setSource(inStream.readLine());
System.out.print("To: ");
System.out.flush();
msg.setDestination(inStream.readLine());
System.out.print("Subject: ");
System.out.flush();
msg.setSubject(inStream.readLine());
System.out.println("Enter message text.");
System.out.println("Terminate message text
with an initial period.");
Vector text = new Vector();
boolean finished = false;
do {
String line = inStream.readLine();
if(endOfText(line)) finished = true;
else text.addElement(line);
} while(!finished);
msg.setText(text);
System.out.println("End of message read.");
}catch (IOException ex) {
System.out.println("IO Exception");
System.exit(1);
}
return msg;
}
boolean endOfText(String s) {
if(s.length() == 0) return false;
if(s.charAt(0) == '.') return true;
return false;
}
}
class MailTalk {
// Communication states
static final int START = 0;
static final int HELO = 1;
static final int MAIL = 2;
static final int RCPT = 3;
static final int DATA = 4;
static final int TEXT = 5;
static final int QUIT = 6;
static final int FINISHED = 9;
Socket connection;
String localHostName;
NVTOutputStream outStream;
NVTInputStream inStream;
Message msg;
public MailTalk(Message msg){
this.msg = msg;
String destination = msg.getDestinationHost();
int port = 25;
try{
connection = new Socket(destination,port);
localHostName = InetAddress.getLocalHost().getHostName();
}catch (UnknownHostException ex)
{ error("Unknown host"); }
catch (IOException ex) { error("IO
error creating socket"); }
try{
outStream = new NVTOutputStream(connection.getOutputStream());
inStream = new NVTInputStream(connection.getInputStream(),outStream);
}catch (IOException ex) { error("IO
error getting streams"); }
System.out.println("Connected to
"+destination+" at port "+port+".");
}
public void run() {
sendMail();
shutdown();
}
public void sendMail() {
try {
int state = START;
String line;
do {
line = inStream.readLine();
if(line == null) state = FINISHED;
else{
System.out.println(line);
switch(state) {
case START:
if(gotResponse(220,line)){
outStream.println("HELO
"+localHostName);
System.out.println(">>>HELO
"+localHostName);
state = HELO;
}else state=FINISHED;
break;
case HELO:
if(gotResponse(250,line)){
outStream.println("MAIL FROM:<"+msg.getSource()+">");
System.out.println(">>>MAIL
FROM:<"+msg.getSource()+">");
state = MAIL;
}else state=FINISHED;
break;
case MAIL:
if(gotResponse(250,line)){
outStream.println("RCPT TO:<"+msg.getDestination()+">");
System.out.println(">>>RCPT
TO:<"+msg.getDestination()+">");
state = RCPT;
}else state=FINISHED;
break;
case RCPT:
if(gotResponse(250,line)){
outStream.println("DATA");
System.out.println(">>>DATA");
state = DATA;
}else state=FINISHED;
break;
case DATA:
if(gotResponse(354,line)){
String text[] = msg.getText();
int len = text.length;
outStream.println("Subject: "+msg.getSubject());
outStream.println("");
System.out.println("Subject: "+msg.getSubject());
System.out.println("");
for(int i=0;i<len;++i) {
if(text[i].length() > 0
&& text[i].charAt(0) == '.') {
outStream.println("."+text[i]);
System.out.println("."+text[i]);
}else{
outStream.println(text[i]);
System.out.println(">>>"+text[i]);
}
}
outStream.println(".");
System.out.println(">>>.");
state = TEXT;
}else state=FINISHED;
break;
case TEXT:
if(gotResponse(250,line)){
outStream.println("QUIT");
System.out.println(">>>QUIT");
state = QUIT;
}else state=FINISHED;
break;
case QUIT:
state=FINISHED;
break;
}
}
} while(state != FINISHED);
} catch(IOException ex) {
error("IO Exception while sending
mail");
}
}
boolean gotResponse(int n,String s) {
try {
int responseCode = Integer.valueOf(s.trim().substring(0,3)).intValue();
String line = s;
while(line.charAt(3) == '-') {
line = inStream.readLine();
System.out.println(line);
}
if(responseCode == n) return true;
}catch(NumberFormatException ex) {
}catch(IOException ex){
}
return false;
}
public void shutdown(){
try{
connection.close();
}catch (IOException ex) { error("IO error closing
socket"); }
}
public void error(String s){
System.out.println(s);
System.exit(1);
}
}
The MailClientApp program
prompts you for the from: name that you want associated with the
sent message. SMTP is inherently insecure and will allow you to
send e-mail using the e-mail address of another person as the
from: address. In the example, I send a message using my daughter's
e-mail address to myself. The subject of the message is Test
Message and it contains a mere two lines of text.
The following output shows a sample dialog with the MailClientApp
program:
C:\java\jdg\ch26>java MailClientApp
From: emily@jaworski.com
To: jamie@jaworski.com
Subject: Test Message
Enter message text.
Terminate message text with an initial period.
This is a test.
It is only a test.
.
End of message read.
Connected to jaworski.com at port 25.
220-jaworski.com Sendmail 8.6.12/8.6.9 ready at Wed, 10 Apr 1996
00:33:31 -0700
220 ESMTP spoken here
>>>HELO athome.jaworski.com
250 jaworski.com Hello athome.jaworski.com [204.212.153.194],
pleased to meet you
>>>MAIL FROM:<emily@jaworski.com>
250 <emily@jaworski.com>... Sender ok
>>>RCPT TO:<jamie@jaworski.com>
250 <jamie@jaworski.com>... Recipient ok
>>>DATA
354 Enter mail, end with "." on a line by itself
Subject: Test Message
>>>This is a test.
>>>It is only a test.
>>>.
250 AAA02243 Message accepted for delivery
>>>QUIT
221 jaworski.com closing connection
C:\java\jdg\ch26>
After the message is received by the e-mail client, it connects
to my SMTP server and sends the message using the SMTP commands
summarized earlier in this chapter.
The >>> arrows indicate
commands that were sent by the program.
The
Web Fetcher Program
Web browsers are the most popular client programs found
on the Internet. They allow users to download and display Web
pages, usually one at a time. The program shown in Listing 26.6
allows the user to specify a list of Web pages to be retrieved,
and retrieves these Web pages and stores them on the local file
system. This is an example of how custom Web clients can be implemented
in Java.
Listing 26.6. The source code for the WebFetchApp
program.
import java.util.Vector;
import java.io.*;
import java.net.*;
public class WebFetchApp {
public static void main(String args[]){
WebFetch fetch = new WebFetch();
fetch.run();
}
}
class WebFetch {
String urlList = "url-list.txt";
Vector URLs = new Vector();
Vector fileNames = new Vector();
public WebFetch() {
super();
}
public void getURLList() {
try {
DataInputStream inStream = new DataInputStream(new
FileInputStream(urlList));
String inLine;
while((inLine = inStream.readLine()) !=
null) {
inLine = inLine.trim();
if(!inLine.equals(""))
{
int tabPos = inLine.lastIndexOf('\t');
String url = inLine.substring(0,tabPos).trim();
String fileName = inLine.substring(tabPos+1).trim();
URLs.addElement(url);
fileNames.addElement(fileName);
}
}
}catch(IOException ex){
error("Error reading "+urlList);
}
}
public void run() {
getURLList();
int numURLs = URLs.size();
for(int i=0;i<numURLs;++i)
fetchURL((String) URLs.elementAt(i),(String) fileNames.elementAt(i));
System.out.println("Done.");
}
public void fetchURL(String urlName,String fileName) {
try{
URL url = new URL(urlName);
System.out.println("Getting "+urlName+"...");
File outFile = new File(fileName);
PrintStream outStream = new PrintStream(new
FileOutputStream(outFile));
DataInputStream inStream = new DataInputStream(url.openStream());
String line;
while ((line = inStream.readLine())!=
null) outStream.println(line);
inStream.close();
outStream.close();
}catch (MalformedURLException ex){
System.out.println("Bad URL");
}catch (IOException ex){
System.out.println("IOException occurred.");
}
}
public void error(String s){
System.out.println(s);
System.exit(1);
}
}
To use the program, create a file named url-list.txt
that contains the names of the URLs you want to retrieve and the
names of the files in which you want them stored. The following
url-list.txt file was used
to retrieve some pretty famous Web pages; it is included on the
CD, in the \jdg\ch26 directory:
http://www.yahoo.com yahoo.htm
http://www.cnn.com cnn.htm
http://home.netscape.com netscape.htm
The output generated for the WebFetchApp
program is as follows:
C:\java\jdg\ch26>java WebFetchApp
Getting http://www.yahoo.com...
Getting http://www.cnn.com...
Getting http://home.netscape.com...
Done.
C:\java\jdg\ch26>
Summary
In this chapter you have learned how to write client programs
that implement the client end of Internet client/server applications.
You have learned about the common client programs found on the
Internet and how they are structured. You have developed a simple
telnet client, an e-mail program, and the Web fetcher program.
In Chapter 27, "Server Programs,"
you'll learn how to write simple server applications.
Contact
reference@developer.com with questions or comments.
Copyright 1998
EarthWeb Inc., All rights reserved.
PLEASE READ THE ACCEPTABLE USAGE STATEMENT.
Copyright 1998 Macmillan Computer Publishing. All rights reserved.
Wyszukiwarka
Podobne podstrony:
ch26ch26ch26 (6)ch26ch26 (13)ch26 (3)ch26ch26ch26 (5)ch26ch26ch26 (10)więcej podobnych podstron