diff -r 115e09b7a004 -r 3acf8e5e2ca0 jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java --- /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. + * + *

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}. + * + *

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. + * + *

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}. + * + *

Socket options are configured using the {@link #setOption(SocketOption,Object) + * setOption} method. Asynchronous socket channels support the following options: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Option NameDescription
{@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} The size of the socket send buffer
{@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} The size of the socket receive buffer
{@link java.net.StandardSocketOption#SO_KEEPALIVE SO_KEEPALIVE} Keep connection alive
{@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} Re-use address
{@link java.net.StandardSocketOption#TCP_NODELAY TCP_NODELAY} Disable the Nagle algorithm
+ *
+ * Additional (implementation specific) options may also be supported. + * + *

Timeouts

+ * + *

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 error state. 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. + * + *

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 default group. + * + * @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. + * + *

This method returns an asynchronous socket channel that is bound to + * the default group.This method is equivalent to evaluating the + * expression: + *

+     * open((AsynchronousChannelGroup)null);
+     * 
+ * + * @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 AsynchronousSocketChannel setOption(SocketOption name, T value) + throws IOException; + + /** + * Shutdown the connection for reading without closing the channel. + * + *

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. + * + *

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. + * + *

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. + * + *

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. + * + *

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 Future connect(SocketAddress remote, + A attachment, + CompletionHandler handler); + + /** + * Connects this channel. + * + *

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 connect(SocketAddress remote) { + return connect(remote, null, null); + } + + /** + * Reads a sequence of bytes from this channel into the given buffer. + * + *

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. + * + *

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. + * + *

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 Future read(ByteBuffer dst, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler 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 Future read(ByteBuffer dst, + A attachment, + CompletionHandler 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 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 scattering read, + * 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. + * + *

This method initiates a read of up to r bytes from this channel, + * where r is the total number of bytes remaining in the specified + * subsequence of the given buffer array, that is, + * + *

+     * dsts[offset].remaining()
+     *     + dsts[offset+1].remaining()
+     *     + ... + dsts[offset+length-1].remaining()
+ * + * at the moment that the read is attempted. + * + *

Suppose that a byte sequence of length n is read, where + * 0 < n <= r. + * Up to the first dsts[offset].remaining() bytes of this sequence + * are transferred into buffer dsts[offset], up to the next + * dsts[offset+1].remaining() bytes are transferred into buffer + * dsts[offset+1], 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. + * + *

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. + * + *

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 Future read(ByteBuffer[] dsts, + int offset, + int length, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler); + + /** + * Writes a sequence of bytes to this channel from the given buffer. + * + *

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. + * + *

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. + * + *

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 Future write(ByteBuffer src, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler 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 Future write(ByteBuffer src, + A attachment, + CompletionHandler 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 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 gathering write, 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. + * + *

This method initiates a write of up to r bytes to this channel, + * where r is the total number of bytes remaining in the specified + * subsequence of the given buffer array, that is, + * + *

+     * srcs[offset].remaining()
+     *     + srcs[offset+1].remaining()
+     *     + ... + srcs[offset+length-1].remaining()
+ * + * at the moment that the write is attempted. + * + *

Suppose that a byte sequence of length n is written, where + * 0 < n <= r. + * Up to the first srcs[offset].remaining() bytes of this sequence + * are written from buffer srcs[offset], up to the next + * srcs[offset+1].remaining() bytes are written from buffer + * srcs[offset+1], 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. + * + *

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. + * + *

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 Future write(ByteBuffer[] srcs, + int offset, + int length, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler); +}