jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java
changeset 2057 3acf8e5e2ca0
child 3632 399359a027de
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java	Sun Feb 15 12:25:54 2009 +0000
@@ -0,0 +1,670 @@
+/*
+ * Copyright 2007-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.nio.channels;
+
+import java.nio.channels.spi.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.Future;
+import java.io.IOException;
+import java.net.SocketOption;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+
+/**
+ * An asynchronous channel for stream-oriented connecting sockets.
+ *
+ * <p> Asynchronous socket channels are created in one of two ways. A newly-created
+ * {@code AsynchronousSocketChannel} is created by invoking one of the {@link
+ * #open open} methods defined by this class. A newly-created channel is open but
+ * not yet connected. A connected {@code AsynchronousSocketChannel} is created
+ * when a connection is made to the socket of an {@link AsynchronousServerSocketChannel}.
+ * It is not possible to create an asynchronous socket channel for an arbitrary,
+ * pre-existing {@link java.net.Socket socket}.
+ *
+ * <p> A newly-created channel is connected by invoking its {@link #connect connect}
+ * method; once connected, a channel remains connected until it is closed.  Whether
+ * or not a socket channel is connected may be determined by invoking its {@link
+ * #getRemoteAddress getRemoteAddress} method. An attempt to invoke an I/O
+ * operation upon an unconnected channel will cause a {@link NotYetConnectedException}
+ * to be thrown.
+ *
+ * <p> Channels of this type are safe for use by multiple concurrent threads.
+ * They support concurrent reading and writing, though at most one read operation
+ * and one write operation can be outstanding at any time.
+ * If a thread initiates a read operation before a previous read operation has
+ * completed then a {@link ReadPendingException} will be thrown. Similarly, an
+ * attempt to initiate a write operation before a previous write has completed
+ * will throw a {@link WritePendingException}.
+ *
+ * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
+ * setOption} method. Asynchronous socket channels support the following options:
+ * <blockquote>
+ * <table border>
+ *   <tr>
+ *     <th>Option Name</th>
+ *     <th>Description</th>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} </td>
+ *     <td> The size of the socket send buffer </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
+ *     <td> The size of the socket receive buffer </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_KEEPALIVE SO_KEEPALIVE} </td>
+ *     <td> Keep connection alive </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
+ *     <td> Re-use address </td>
+ *   </tr>
+ *   <tr>
+ *     <td> {@link java.net.StandardSocketOption#TCP_NODELAY TCP_NODELAY} </td>
+ *     <td> Disable the Nagle algorithm </td>
+ *   </tr>
+ * </table>
+ * </blockquote>
+ * Additional (implementation specific) options may also be supported.
+ *
+ * <h4>Timeouts</h4>
+ *
+ * <p> The {@link #read(ByteBuffer,long,TimeUnit,Object,CompletionHandler) read}
+ * and {@link #write(ByteBuffer,long,TimeUnit,Object,CompletionHandler) write}
+ * methods defined by this class allow a timeout to be specified when initiating
+ * a read or write operation. If the timeout elapses before an operation completes
+ * then the operation completes with the exception {@link
+ * InterruptedByTimeoutException}. A timeout may leave the channel, or the
+ * underlying connection, in an inconsistent state. Where the implementation
+ * cannot guarantee that bytes have not been read from the channel then it puts
+ * the channel into an implementation specific <em>error state</em>. A subsequent
+ * attempt to initiate a {@code read} operation causes an unspecified runtime
+ * exception to be thrown. Similarly if a {@code write} operation times out and
+ * the implementation cannot guarantee bytes have not been written to the
+ * channel then further attempts to {@code write} to the channel cause an
+ * unspecified runtime exception to be thrown. When a timeout elapses then the
+ * state of the {@link ByteBuffer}, or the sequence of buffers, for the I/O
+ * operation is not defined. Buffers should be discarded or at least care must
+ * be taken to ensure that the buffers are not accessed while the channel remains
+ * open.
+ *
+ * @since 1.7
+ */
+
+public abstract class AsynchronousSocketChannel
+    implements AsynchronousByteChannel, NetworkChannel
+{
+    private final AsynchronousChannelProvider provider;
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    protected AsynchronousSocketChannel(AsynchronousChannelProvider provider) {
+        this.provider = provider;
+    }
+
+    /**
+     * Returns the provider that created this channel.
+     */
+    public final AsynchronousChannelProvider provider() {
+        return provider;
+    }
+
+    /**
+     * Opens an asynchronous socket channel.
+     *
+     * <p> The new channel is created by invoking the {@link
+     * AsynchronousChannelProvider#openAsynchronousSocketChannel
+     * openAsynchronousSocketChannel} method on the {@link
+     * AsynchronousChannelProvider} that created the group. If the group parameter
+     * is {@code null} then the resulting channel is created by the system-wide
+     * default provider, and bound to the <em>default group</em>.
+     *
+     * @param   group
+     *          The group to which the newly constructed channel should be bound,
+     *          or {@code null} for the default group
+     *
+     * @return  A new asynchronous socket channel
+     *
+     * @throws  ShutdownChannelGroupException
+     *          If the channel group is shutdown
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousSocketChannel open(AsynchronousChannelGroup group)
+        throws IOException
+    {
+        AsynchronousChannelProvider provider = (group == null) ?
+            AsynchronousChannelProvider.provider() : group.provider();
+        return provider.openAsynchronousSocketChannel(group);
+    }
+
+    /**
+     * Opens an asynchronous socket channel.
+     *
+     * <p> This method returns an asynchronous socket channel that is bound to
+     * the <em>default group</em>.This method is equivalent to evaluating the
+     * expression:
+     * <blockquote><pre>
+     * open((AsynchronousChannelGroup)null);
+     * </pre></blockquote>
+     *
+     * @return  A new asynchronous socket channel
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static AsynchronousSocketChannel open()
+        throws IOException
+    {
+        return open(null);
+    }
+
+
+    // -- socket options and related --
+
+    /**
+     * @throws  ConnectionPendingException
+     *          If a connection operation is already in progress on this channel
+     * @throws  AlreadyBoundException               {@inheritDoc}
+     * @throws  UnsupportedAddressTypeException     {@inheritDoc}
+     * @throws  ClosedChannelException              {@inheritDoc}
+     * @throws  IOException                         {@inheritDoc}
+     */
+    @Override
+    public abstract AsynchronousSocketChannel bind(SocketAddress local)
+        throws IOException;
+
+    /**
+     * @throws  IllegalArgumentException                {@inheritDoc}
+     * @throws  ClosedChannelException                  {@inheritDoc}
+     * @throws  IOException                             {@inheritDoc}
+     */
+    @Override
+    public abstract <T> AsynchronousSocketChannel setOption(SocketOption<T> name, T value)
+        throws IOException;
+
+    /**
+     * Shutdown the connection for reading without closing the channel.
+     *
+     * <p> Once shutdown for reading then further reads on the channel will
+     * return {@code -1}, the end-of-stream indication. If the input side of the
+     * connection is already shutdown then invoking this method has no effect.
+     * The effect on an outstanding read operation is system dependent and
+     * therefore not specified. The effect, if any, when there is data in the
+     * socket receive buffer that has not been read, or data arrives subsequently,
+     * is also system dependent.
+     *
+     * @return  The channel
+     *
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract AsynchronousSocketChannel shutdownInput() throws IOException;
+
+    /**
+     * Shutdown the connection for writing without closing the channel.
+     *
+     * <p> Once shutdown for writing then further attempts to write to the
+     * channel will throw {@link ClosedChannelException}. If the output side of
+     * the connection is already shutdown then invoking this method has no
+     * effect. The effect on an outstanding write operation is system dependent
+     * and therefore not specified.
+     *
+     * @return  The channel
+     *
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ClosedChannelException
+     *          If this channel is closed
+     * @throws  IOException
+     *          If some other I/O error occurs
+     */
+    public abstract AsynchronousSocketChannel shutdownOutput() throws IOException;
+
+    // -- state --
+
+    /**
+     * Returns the remote address to which this channel's socket is connected.
+     *
+     * <p> Where the channel is bound and connected to an Internet Protocol
+     * socket address then the return value from this method is of type {@link
+     * java.net.InetSocketAddress}.
+     *
+     * @return  The remote address; {@code null} if the channel's socket is not
+     *          connected
+     *
+     * @throws  ClosedChannelException
+     *          If the channel is closed
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public abstract SocketAddress getRemoteAddress() throws IOException;
+
+    // -- asynchronous operations --
+
+    /**
+     * Connects this channel.
+     *
+     * <p> This method initiates an operation to connect this channel, returning
+     * a {@code Future} representing the pending result of the operation. If
+     * the connection is successfully established then the {@code Future}'s
+     * {@link Future#get() get} method will return {@code null}. If the
+     * connection cannot be established then the channel is closed. In that case,
+     * invoking the {@code get} method throws {@link
+     * java.util.concurrent.ExecutionException} with an {@code IOException} as
+     * the cause.
+     *
+     * <p> This method performs exactly the same security checks as the {@link
+     * java.net.Socket} class.  That is, if a security manager has been
+     * installed then this method verifies that its {@link
+     * java.lang.SecurityManager#checkConnect checkConnect} method permits
+     * connecting to the address and port number of the given remote endpoint.
+     *
+     * @param   remote
+     *          The remote address to which this channel is to be connected
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  UnresolvedAddressException
+     *          If the given remote address is not fully resolved
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given remote address is not supported
+     * @throws  AlreadyConnectedException
+     *          If this channel is already connected
+     * @throws  ConnectionPendingException
+     *          If a connection operation is already in progress on this channel
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     * @throws  SecurityException
+     *          If a security manager has been installed
+     *          and it does not permit access to the given remote endpoint
+     *
+     * @see #getRemoteAddress
+     */
+    public abstract <A> Future<Void> connect(SocketAddress remote,
+                                             A attachment,
+                                             CompletionHandler<Void,? super A> handler);
+
+    /**
+     * Connects this channel.
+     *
+     * <p> This method is equivalent to invoking {@link
+     * #connect(SocketAddress,Object,CompletionHandler)} with the {@code attachment}
+     * and handler parameters set to {@code null}.
+     *
+     * @param   remote
+     *          The remote address to which this channel is to be connected
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  UnresolvedAddressException
+     *          If the given remote address is not fully resolved
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given remote address is not supported
+     * @throws  AlreadyConnectedException
+     *          If this channel is already connected
+     * @throws  ConnectionPendingException
+     *          If a connection operation is already in progress on this channel
+     * @throws  SecurityException
+     *          If a security manager has been installed
+     *          and it does not permit access to the given remote endpoint
+     */
+    public final Future<Void> connect(SocketAddress remote) {
+        return connect(remote, null, null);
+    }
+
+    /**
+     * Reads a sequence of bytes from this channel into the given buffer.
+     *
+     * <p> This method initiates the reading of a sequence of bytes from this
+     * channel into the given buffer, returning a {@code Future} representing
+     * the pending result of the operation. The {@code Future}'s {@link
+     * Future#get() get} method returns the number of bytes read or {@code -1}
+     * if all bytes have been read and channel has reached end-of-stream.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then the operation completes with the exception {@link
+     * InterruptedByTimeoutException}. Where a timeout occurs, and the
+     * implementation cannot guarantee that bytes have not been read, or will not
+     * be read from the channel into the given buffer, then further attempts to
+     * read from the channel will cause an unspecific runtime exception to be
+     * thrown.
+     *
+     * <p> Otherwise this method works in the same manner as the {@link
+     * AsynchronousByteChannel#read(ByteBuffer,Object,CompletionHandler)}
+     * method.
+     *
+     * @param   dst
+     *          The buffer into which bytes are to be transferred
+     * @param   timeout
+     *          The timeout, or {@code 0L} for no timeout
+     * @param   unit
+     *          The time unit of the {@code timeout} argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the {@code timeout} parameter is negative or the buffer is
+     *          read-only
+     * @throws  ReadPendingException
+     *          If a read operation is already in progress on this channel
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<Integer> read(ByteBuffer dst,
+                                             long timeout,
+                                             TimeUnit unit,
+                                             A attachment,
+                                             CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * @throws  IllegalArgumentException        {@inheritDoc}
+     * @throws  ReadPendingException            {@inheritDoc}
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    @Override
+    public final <A> Future<Integer> read(ByteBuffer dst,
+                                          A attachment,
+                                          CompletionHandler<Integer,? super A> handler)
+    {
+        return read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+    }
+
+    /**
+     * @throws  IllegalArgumentException        {@inheritDoc}
+     * @throws  ReadPendingException            {@inheritDoc}
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     */
+    @Override
+    public final Future<Integer> read(ByteBuffer dst) {
+        return read(dst, 0L, TimeUnit.MILLISECONDS, null, null);
+    }
+
+    /**
+     * Reads a sequence of bytes from this channel into a subsequence of the
+     * given buffers. This operation, sometimes called a <em>scattering read</em>,
+     * is often useful when implementing network protocols that group data into
+     * segments consisting of one or more fixed-length headers followed by a
+     * variable-length body.
+     *
+     * <p> This method initiates a read of up to <i>r</i> bytes from this channel,
+     * where <i>r</i> is the total number of bytes remaining in the specified
+     * subsequence of the given buffer array, that is,
+     *
+     * <blockquote><pre>
+     * dsts[offset].remaining()
+     *     + dsts[offset+1].remaining()
+     *     + ... + dsts[offset+length-1].remaining()</pre></blockquote>
+     *
+     * at the moment that the read is attempted.
+     *
+     * <p> Suppose that a byte sequence of length <i>n</i> is read, where
+     * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
+     * Up to the first <tt>dsts[offset].remaining()</tt> bytes of this sequence
+     * are transferred into buffer <tt>dsts[offset]</tt>, up to the next
+     * <tt>dsts[offset+1].remaining()</tt> bytes are transferred into buffer
+     * <tt>dsts[offset+1]</tt>, and so forth, until the entire byte sequence
+     * is transferred into the given buffers.  As many bytes as possible are
+     * transferred into each buffer, hence the final position of each updated
+     * buffer, except the last updated buffer, is guaranteed to be equal to
+     * that buffer's limit. The underlying operating system may impose a limit
+     * on the number of buffers that may be used in an I/O operation. Where the
+     * number of buffers (with bytes remaining), exceeds this limit, then the
+     * I/O operation is performed with the maximum number of buffers allowed by
+     * the operating system.
+     *
+     * <p> The return value from this method is a {@code Future} representing
+     * the pending result of the operation. The {@code Future}'s {@link
+     * Future#get() get} method returns the number of bytes read or {@code -1L}
+     * if all bytes have been read and the channel has reached end-of-stream.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then it completes with the exception {@link
+     * InterruptedByTimeoutException}. Where a timeout occurs, and the
+     * implementation cannot guarantee that bytes have not been read, or will not
+     * be read from the channel into the given buffers, then further attempts to
+     * read from the channel will cause an unspecific runtime exception to be
+     * thrown.
+     *
+     * @param   dsts
+     *          The buffers into which bytes are to be transferred
+     * @param   offset
+     *          The offset within the buffer array of the first buffer into which
+     *          bytes are to be transferred; must be non-negative and no larger than
+     *          {@code dsts.length}
+     * @param   length
+     *          The maximum number of buffers to be accessed; must be non-negative
+     *          and no larger than {@code dsts.length - offset}
+     * @param   timeout
+     *          The timeout, or {@code 0L} for no timeout
+     * @param   unit
+     *          The time unit of the {@code timeout} argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the pre-conditions for the {@code offset}  and {@code length}
+     *          parameter aren't met
+     * @throws  IllegalArgumentException
+     *          If the {@code timeout} parameter is negative, or a buffer is
+     *          read-only
+     * @throws  ReadPendingException
+     *          If a read operation is already in progress on this channel
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<Long> read(ByteBuffer[] dsts,
+                                          int offset,
+                                          int length,
+                                          long timeout,
+                                          TimeUnit unit,
+                                          A attachment,
+                                          CompletionHandler<Long,? super A> handler);
+
+    /**
+     * Writes a sequence of bytes to this channel from the given buffer.
+     *
+     * <p> This method initiates the writing of a sequence of bytes to this channel
+     * from the given buffer, returning a {@code Future} representing the
+     * pending result of the operation. The {@code Future}'s {@link Future#get()
+     * get} method will return the number of bytes written.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then it completes with the exception {@link
+     * InterruptedByTimeoutException}. Where a timeout occurs, and the
+     * implementation cannot guarantee that bytes have not been written, or will
+     * not be written to the channel from the given buffer, then further attempts
+     * to write to the channel will cause an unspecific runtime exception to be
+     * thrown.
+     *
+     * <p> Otherwise this method works in the same manner as the {@link
+     * AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)}
+     * method.
+     *
+     * @param   src
+     *          The buffer from which bytes are to be retrieved
+     * @param   timeout
+     *          The timeout, or {@code 0L} for no timeout
+     * @param   unit
+     *          The time unit of the {@code timeout} argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  IllegalArgumentException
+     *          If the {@code timeout} parameter is negative
+     * @throws  WritePendingException
+     *          If a write operation is already in progress on this channel
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<Integer> write(ByteBuffer src,
+                                              long timeout,
+                                              TimeUnit unit,
+                                              A attachment,
+                                              CompletionHandler<Integer,? super A> handler);
+
+    /**
+     * @throws  WritePendingException          {@inheritDoc}
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    @Override
+    public final <A> Future<Integer> write(ByteBuffer src,
+                                           A attachment,
+                                           CompletionHandler<Integer,? super A> handler)
+
+    {
+        return write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+    }
+
+    /**
+     * @throws  WritePendingException       {@inheritDoc}
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     */
+    @Override
+    public final Future<Integer> write(ByteBuffer src) {
+        return write(src, 0L, TimeUnit.MILLISECONDS, null, null);
+    }
+
+    /**
+     * Writes a sequence of bytes to this channel from a subsequence of the given
+     * buffers. This operation, sometimes called a <em>gathering write</em>, is
+     * often useful when implementing network protocols that group data into
+     * segments consisting of one or more fixed-length headers followed by a
+     * variable-length body.
+     *
+     * <p> This method initiates a write of up to <i>r</i> bytes to this channel,
+     * where <i>r</i> is the total number of bytes remaining in the specified
+     * subsequence of the given buffer array, that is,
+     *
+     * <blockquote><pre>
+     * srcs[offset].remaining()
+     *     + srcs[offset+1].remaining()
+     *     + ... + srcs[offset+length-1].remaining()</pre></blockquote>
+     *
+     * at the moment that the write is attempted.
+     *
+     * <p> Suppose that a byte sequence of length <i>n</i> is written, where
+     * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
+     * Up to the first <tt>srcs[offset].remaining()</tt> bytes of this sequence
+     * are written from buffer <tt>srcs[offset]</tt>, up to the next
+     * <tt>srcs[offset+1].remaining()</tt> bytes are written from buffer
+     * <tt>srcs[offset+1]</tt>, and so forth, until the entire byte sequence is
+     * written.  As many bytes as possible are written from each buffer, hence
+     * the final position of each updated buffer, except the last updated
+     * buffer, is guaranteed to be equal to that buffer's limit. The underlying
+     * operating system may impose a limit on the number of buffers that may be
+     * used in an I/O operation. Where the number of buffers (with bytes
+     * remaining), exceeds this limit, then the I/O operation is performed with
+     * the maximum number of buffers allowed by the operating system.
+     *
+     * <p> The return value from this method is a {@code Future} representing
+     * the pending result of the operation. The {@code Future}'s {@link
+     * Future#get() get} method will return the number of bytes written.
+     *
+     * <p> If a timeout is specified and the timeout elapses before the operation
+     * completes then it completes with the exception {@link
+     * InterruptedByTimeoutException}. Where a timeout occurs, and the
+     * implementation cannot guarantee that bytes have not been written, or will
+     * not be written to the channel from the given buffers, then further attempts
+     * to write to the channel will cause an unspecific runtime exception to be
+     * thrown.
+     *
+     * @param   srcs
+     *          The buffers from which bytes are to be retrieved
+     * @param   offset
+     *          The offset within the buffer array of the first buffer from which
+     *          bytes are to be retrieved; must be non-negative and no larger
+     *          than {@code srcs.length}
+     * @param   length
+     *          The maximum number of buffers to be accessed; must be non-negative
+     *          and no larger than {@code srcs.length - offset}
+     * @param   timeout
+     *          The timeout, or {@code 0L} for no timeout
+     * @param   unit
+     *          The time unit of the {@code timeout} argument
+     * @param   attachment
+     *          The object to attach to the I/O operation; can be {@code null}
+     * @param   handler
+     *          The handler for consuming the result; can be {@code null}
+     *
+     * @return  A {@code Future} object representing the pending result
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the pre-conditions for the {@code offset}  and {@code length}
+     *          parameter aren't met
+     * @throws  IllegalArgumentException
+     *          If the {@code timeout} parameter is negative
+     * @throws  WritePendingException
+     *          If a write operation is already in progress on this channel
+     * @throws  NotYetConnectedException
+     *          If this channel is not yet connected
+     * @throws  ShutdownChannelGroupException
+     *          If a handler is specified, and the channel group is shutdown
+     */
+    public abstract <A> Future<Long> write(ByteBuffer[] srcs,
+                                           int offset,
+                                           int length,
+                                           long timeout,
+                                           TimeUnit unit,
+                                           A attachment,
+                                           CompletionHandler<Long,? super A> handler);
+}