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

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

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

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

Harold, Elliotte Rusty

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

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

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








12.5 Readiness Selection


For network programming, the second
part of the new I/O APIs is readiness selection, the ability to
choose a socket that will not block when read or written. This is
primarily of interest to servers, although clients running multiple
simultaneous connections with several windows opensuch as a
web spider or a browsercan take advantage of it as well.

In order to perform readiness selection, different channels are
registered with a Selector object. Each channel is
assigned a SelectionKey. The program can then ask
the Selector object for the set of keys to the
channels that are ready to perform the operation you want to perform
without blocking.


12.5.1 The Selector Class


The only constructor in
Selector is protected. Normally, a new selector is
created by invoking the static factory method Selector.open(
)
:

public static Selector open( ) throws IOException

The next step is to add channels to the selector. There are no
methods in the Selector class to add a channel.
The register( ) method is
declared in the
SelectableChannel class. Not all channels are
selectablein particular, FileChannels
aren't selectablebut all network channels
are. Thus, the channel is registered with a selector by passing the
selector to one of the channel's register methods:

public final SelectionKey register(Selector sel, int ops) 
throws ClosedChannelException
public final SelectionKey register(Selector sel, int ops, Object att)
throws ClosedChannelException

This approach feels backwards to me, but it's not
hard to use. The first argument is the selector the channel is
registering with. The second argument is a named constant from the
SelectionKey class identifying the operation the
channel is registering for. The
SelectionKey
class defines four named bit constants used to select the type of the
operation:

SelectionKey.OP_ACCEPT

SelectionKey.OP_CONNECT

SelectionKey.OP_READ

SelectionKey.OP_WRITE


These are bit-flag int constants (1, 2, 4, etc.). Therefore, if a
channel needs to register for multiple operations in the same
selector (e.g., for both reading and writing on a socket), combine
the constants with the bitwise or operator (|)
when registering:

channel.register(selector,  SelectionKey.OP_READ | SelectionKey.OP_WRITE);

The optional third argument is an attachment for the key. This object
is often used to store state for the connection. For example, if you
were implementing a web server, you might attach a
FileInputStream or FileChannel
connected to the local file the server streams to the client.

After the different channels have been registered with the selector,
you can query the selector at any time to find out which channels are
ready to be processed. Channels may be ready for some operations and
not others. For instance, a channel could be ready for reading but
not writing.

There are three methods that select the ready channels. They differ
in how long they wait to find a ready channel. The first,
selectNow( ), performs a
non-blocking select. It returns immediately if no connections are
ready to be processed now:

public abstract int selectNow( ) throws IOException

The other two select methods are blocking:

public abstract int select( ) throws IOException
public abstract int select(long timeout) throws IOException

The first method waits until at least one registered channel is ready
to be processed before returning. The second waits no longer than
timeout milliseconds for a channel to be ready
before returning 0. These methods are useful if your program
doesn't have anything to do when no channels are
ready to be processed.

When you know the channels are ready to be processed, retrieve the
ready channels using selectedKeys():

public abstract Set selectedKeys( )

The return value is just a standard java.util.Set.
Each item in the set is a SelectionKey object. You
can iterate through it in the usual way, casting each item to
SelectionKey in turn. You'll also
want to remove the key from the iterator to tell the
Selector that you've handled it.
Otherwise, the Selector will keep telling you
about it on future passes through the loop.

Finally, when you're ready to shut the server down
or when you no longer need the Selector, you
should close it:

public abstract void close( ) throws IOException

This step releases any resources associated with the selector. More
importantly, it cancels all keys registered with the selector and
interrupts up any threads blocked by one of this
selector's select methods.


12.5.2 The SelectionKey Class


SelectionKey objects serve as pointers to channels.
They can also hold an object attachment, which is how you normally
store the state for the connection on that channel.

SelectionKey objects are returned by the
register( ) method when registering a channel with
a Selector. However, you don't
usually need to retain this reference. The selectedKeys(
)
method returns the same objects again
inside a Set. A single channel can be registered
with multiple selectors.

When retrieving a SelectionKey from the set of
selected keys, you often first test what that key is ready to do.
There are four possibilities:

public final boolean isAcceptable( )
public final boolean isConnectable( )
public final boolean isReadable( )
public final boolean isWritable( )

This test isn't always necessary. In some cases, the
Selector is only testing for one possibility and
will only return keys to do that one thing. But if the
Selector does test for multiple readiness states,
you'll want to test which one kicked the channel
into the ready state before operating on it. It's
also possible that a channel is ready to do more than one thing.

Once you know what the channel associated with the key is ready to
do, retrieve the channel with the channel( )
method:

public abstract SelectableChannel channel( )

If you've stored an object in the
SelectionKey to hold state information, you can
retrieve it with the attachment(
)
method:

public final Object attachment( )

Finally, when you're finished with a connection,
deregister its SelectionKey object so the
Selector doesn't waste any
resources querying it for readiness. I don't know
that this is absolutely essential in all cases, but it
doesn't hurt. You do this by invoking the
key's cancel() method:

public abstract void cancel( )

However, this step is only necessary if you haven't
closed the channel. Closing a channel automatically deregisters all
keys for that channel in all selectors. Similarly, closing a selector
invalidates all keys in that selector.


/ 164