Java Reference
In-Depth Information
When implementing a client that takes advantage of the new I/O APIs, begin by invoking
the static factory method
SocketChannel.open()
to create a new
java.nio.chan
nels.SocketChannel
object. The argument to this method is a
java.net.SocketAd
dress
object indicating the host and port to connect to. For example, this fragment
connects the channel to
rama.poly.edu
on port 19:
SocketAddress
rama
=
new
InetSocketAddress
(
"rama.poly.edu"
,
19
);
SocketChannel
client
=
SocketChannel
.
open
(
rama
);
The channel is opened in blocking mode, so the next line of code won't execute until
the connection is established. If the connection can't be established, an
IOException
is
thrown.
If this were a traditional client, you'd now ask for the socket's input and/or output
streams. However, it's not. With a channel you write directly to the channel itself. Rather
than writing byte arrays, you write
ByteBuffer
objects. You've got a pretty good idea
that the lines of text are 74 ASCII characters long (72 printable characters followed by
a carriage return/linefeed pair) so you'll create a
ByteBuffer
that has a 74-byte capacity
using the static
allocate()
method:
ByteBuffer
buffer
=
ByteBuffer
.
allocate
(
74
);
Pass this
ByteBuffer
object to the channel's
read()
method. The channel fills this buffer
with the data it reads from the socket. It returns the number of bytes it successfully read
and stored in the buffer:
int
bytesRead
=
client
.
read
(
buffer
);
By default, this will read at least one byte or return -1 to indicate the end of the data,
exactly as an
InputStream
does. It will often read more bytes if more bytes are available
to be read. Shortly you'll see how to put this client in nonblocking mode where it will
return 0 immediately if no bytes are available, but for the moment this code blocks just
like an
InputStream
. As you could probably guess, this method can also throw an
IOException
if anything goes wrong with the read.
Assuming there is some data in the buffer—that is, n > 0—this data can be copied to
System.out
. There are ways to extract a byte array from a
ByteBuffer
that can then be
written on a traditional
OutputStream
such as
System.out
. However, it's more infor‐
mative to stick with a pure, channel-based solution. Such a solution requires wrapping
the
OutputStream
System.out
in a channel using the
Channels
utility class, specifically,
its
newChannel()
method:
WritableByteChannel
output
=
Channels
.
newChannel
(
System
.
out
);
You can then write the data that was read onto this output channel connected to
System.out
. However, before you do that, you have to
flip
the buffer so that the output
channel starts from the beginning of the data that was read rather than the end: