Java Network Programming (3rd ed) [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Java Network Programming (3rd ed) [Electronic resources] - نسخه متنی

Harold, Elliotte Rusty

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








16.3 Writing a Protocol Handler


To
demonstrate a complete protocol handler, let's write
one for the finger protocol defined in RFC 1288 and
introduced in Chapter 9. Finger is a relatively
simple protocol compared to JDK-supported protocols such as HTTP and
FTP. The client connects to port 79 on the server and sends a list of
usernames followed by a carriage return/linefeed pair. The server
responds with ASCII text containing information about each of the
named users or, if no names are listed, a list of the currently
logged in users. For example:

% telnet rama.poly.edu 79
Trying 128.238.10.212...
Connected to rama.poly.edu.
Escape character is '^]'.
Login Name TTY Idle When Where
jacola Jane Colaginae *pts/7 Tue 08:01 208.34.37.104
marcus Marcus Tullius pts/15 13d Tue 17:33 farm-dialup11.poly.e
matewan Sepin Matewan *pts/17 17: Thu 15:32 128.238.10.177
hengpi Heng Pin *pts/10 Tue 10:36 128.238.18.119
nadats Nabeel Datsun pts/12 56 Mon 10:38 128.238.213.227
matewan Sepin Matewan *pts/8 4 Sun 18:39 128.238.10.177
Connection closed by foreign host.

Or to request information about a specific user:

% telnet rama.poly.edu 79
Trying 128.238.10.212...
Connected to rama.poly.edu.
Escape character is '^]'.
marcus
Login Name TTY Idle When Where
marcus Marcus Tullius pts/15 13d Tue 17:33 farm-dialup11.poly.e

Since there's no standard for the format of a finger
URL, we will start by creating one. Ideally, this should look as much
like an http URL as possible. Therefore, we will
implement a finger URL like this:

finger://hostname:port/usernames

Second, we need to determine the content type returned by the finger
protocol's getContentType() method. New protocols such as HTTP use MIME
headers to indicate the content type; in these cases, you do not need
to override the default getContentType( ) method
provided by the URLConnection class. However,
since most protocols precede MIME, you often need to specify the MIME
type explicitly or use the static methods
URLConnection.guessContentTypeFromName(String
name) and
URLConnection.guessContentTypeFromStream(InputStream
in) to make an educated guess. This example
doesn't need anything so complicated, however. A
finger server returns ASCII text, so the getContentType() method should return the string
text/plain. The text/plain MIME
type has the advantage that Java already understands it. In the next
chapter, you'll learn how to write content handlers
that let Java understand additional MIME types.

Example 16-2 is a
FingerURLConnection class that subclasses
URLConnection. This class overrides the
getContentType( ) and getInputStream(
)
methods of URLConnection and
implements connect( ). It also has a constructor
that builds a new URLConnection from a URL.


Example 16-2. The FingerURLConnection class


package com.macfaq.net.www.protocol.finger;
import java.net.*;
import java.io.*;
public class FingerURLConnection extends URLConnection {
private Socket connection = null;
public final static int DEFAULT_PORT = 79;
public FingerURLConnection(URL u) {
super(u);
}
public synchronized InputStream getInputStream( ) throws IOException {
if (!connected) this.connect( );
InputStream in = this.connection.getInputStream( );
return in;
}
public String getContentType( ) {
return "text/plain";
}
public synchronized void connect( ) throws IOException {
if (!connected) {
int port = url.getPort( );
if ( port < 1 || port > 65535) {
port = DEFAULT_PORT;
}
this.connection = new Socket(url.getHost( ), port);
OutputStream out = this.connection.getOutputStream( );
String names = url.getFile( );
if (names != null && !names.equals(")) {
// delete initial /
names = names.substring(1);
names = URLDecoder.decode(names);
byte[] result;
try {
result = names.getBytes("ASCII");
}
catch (UnsupportedEncodingException ex) {
result = names.getBytes( );
}
out.write(result);
}
out.write('\r');
out.write('\n');
out.flush( );
this.connected = true;
}
}
}

This class has two fields. connection is a
Socket between the client and the server. Both the
getInputStream( ) method and the connect() method need access to this field, so it
can't be a local variable. The second field is
DEFAULT_PORT, a final
static int, which contains the
finger protocol's default port; this port is used if
the URL does not specify the port explicitly.

The class's constructor holds no surprises. It just
calls the superclass's constructor with the same
argument, the URL u. The
connect( ) method opens a connection to the
specified server on the specified port or, if no port is specified,
to the default finger port, 79. It sends the necessary request to the
finger server. If any usernames were specified in the file part of
the URL, they're sent. Otherwise, a blank line is
sent. Assuming the connection is successfully opened (no exception is
thrown), it sets the boolean field
connected to true. Recall from
the previous chapter that connected is a protected
field in java.net.URLConnection, which is
inherited by this subclass. The Socket that
connect( ) opens is stored in the field
connection for later use by
getInputStream( ). The connect(
)
and getInputStream( ) methods are
synchronized to avoid a possible race condition on the
connected variable.

The getContentType( ) method returns a
String containing a MIME type for the data. This
is used by the getContent( ) method of
java.net.URLConnection to select the appropriate
content handler. The data returned by a finger server is almost
always ASCII text or some reasonable approximation thereof, so this
getContentType( ) method always returns
text/plain. The getInputStream(
)
method returns an InputStream, which
it gets from the Socket that
connect created. If the connection has not already
been established when getInputStream( ) is called,
the method calls connect( ) itself.

Once you have a URLConnection, you need a subclass
of URLStreamHandler that knows how to handle a
finger server. This class needs an openConnection() method that builds a new
FingerURLConnection from a URL. Since we defined
the finger URL as a hierarchical URL, we
don't need to implement a parseURL() method. Example 16-3 is a stream handler
for the finger protocol. For the moment, we're going
to use Sun's convention for naming protocol
handlers; we call this class Handler and place it
in the package com.macfaq.net.www.protocol.finger.


Example 16-3. The finger handler class


package com.macfaq.net.www.protocol.finger;
import java.net.*;
import java.io.*;
public class Handler extends URLStreamHandler {
public int getDefaultPort( ) {
return 79;
}
protected URLConnection openConnection(URL u) throws IOException {
return new FingerURLConnection(u);
}
}

You can use HotJava to test this protocol
handler. Add the following line to your
.hotjava/properties file or some other place
from which HotJava will load it:

java.protocol.handler.pkgs=com.macfaq.net.www.protocol

Some (but not all) versions of HotJava may also allow you to set the
property from the command line:

% hotjava -Djava.protocol.handler.pkgs=com.macfaq.net.www.protocol

You also need to make sure that your classes are somewhere in
HotJava's class path. HotJava does not normally use
the CLASSPATH environment variable to look for classes, so just
putting them someplace where the JDK or JRE can find them may not be
sufficient. Using HotJava 3.0 on Windows with the JDK 1.3, I was able
to put my classes in the jdk1.3/jre/lib/classes
folder. Your mileage may vary depending on the version of HotJava
you're using with which version of the JDK on which
platform.

Run it and ask for a URL of a site running finger, such as
utopia.poly.edu. Figure 16-1
shows the result.


Figure 16-1. HotJava using the finger protocol handler


/ 164