Java Reference
In-Depth Information
The processing of data from an existing connection involves making use of the
ByteBuffer
object created earlier. Buffer method
clear
(the purpose of which is
self-evident) should be called before each fresh reading of data into the buffer
from its associated channel. A reference to the channel is obtained by calling
method
channel
on the current
SelectionKey
and again typecasting the
Object
reference that is returned. The reading itself is carried out by method
read
of the
SocketChannel
class. This method takes the buffer as its single argument and
returns an integer that indicates the number of bytes read. The lines to obtain the
SocketChannel
reference, clear the
ByteBuffer
and read data from the channel into
the buffer are as follows:
socketChannel = (SocketChannel)key.channel();
buffer.clear();
int numBytes = socketChannel.read(buffer);
In order to write the data from the buffer to the channel, it is necessary to call
Buffer
method
fl i p
to reset the buffer pointer to the start of the buffer and then call
method
write
on the channel object, supplying the buffer as the single argument. In
the example at the end of this section (which will contain all the code accumulated
within the section), the data received will simply be echoed back to the client. Since
it may not be possible to send the entire contents of the buffer in one operation, a
while
loop will be used, with
Buffer
method
remaining
being called to determine
whether there are any bytes still to be sent. Since an
IOException
may be generated,
this code will need to be contained within a
try
block, but the basic code (without
the
try
) is shown below.
buffer.fl ip();
while (buffer.remaining()>0)
socketChannel.write(buffer);
Note that whereas, with the multithreading approach, we had separate streams
for input and output, the
SocketChannel
is a two-way conduit and provides all the
I/O requirements between server and client. Note also that reading and writing is
specifi ed with respect to the
channel
. It can be very easy at fi rst viewing to interpret
socketChannel.read(buffer)
as being 'read from buffer' and
sock-
etChannel.write(buffer)
as being 'write to buffer', whereas this is pre-
cisely the
opposite
of what is actually happening.
The link between client and server can break down, of course, possibly because
the connection has been closed at the client end or possibly because of some error
situation. Whatever the reason, this must be taken into account when attempting to
read from the
SocketChannel
. If a breakdown occurs, then the call to method
read
will return −1. When this happens, the registration of the current
SelectionKey
with
the
Selector
object must be rescinded. This is done by calling method
cancel
on the
SelectionKey
object. The socket associated with the client should also be closed.
Before this can be done, it is necessary to get a reference to the
Socket
object by
calling method
socket
on the
SocketChannel
object. The (attempted) closure of the
socket may fail and needs to be executed within a
try
block, but the example
Search WWH ::
Custom Search