/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.nio.channels;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.SelectorProvider;
import org.apache.harmony.luni.platform.Platform;
/**
* A {@code SocketChannel} is a selectable channel that provides a partial
* abstraction of stream connecting socket. {@code socket()} returns the related
* {@link Socket} instance which can handle the socket.
* <p>
* A socket channel is open but not connected when created by {@code open()}.
* After connecting it by calling {@code connect(SocketAddress)}, it will remain
* connected until it gets closed. If the connection is non-blocking then
* {@code connect(SocketAddress)} is used to initiate the connection, followed
* by a call of {@code finishConnect()} to perform the final steps of
* connecting. {@code isConnectionPending()} indicates if the connection is
* blocked or not; {@code isConnected()} indicates if the socket is finally
* connected or not.
* </p>
* <p>
* The input and output sides of a channel can be shut down independently and
* asynchronously without closing the channel. The {@code shutdownInput} method
* is used for the input side of a channel and subsequent read operations return
* -1, which means end of stream. If another thread is blocked in a read
* operation when the shutdown occurs, the read will end without effect and
* return end of stream. The {@code shutdownOutput} method is used for the
* output side of the channel; subsequent write operations throw a
* {@link ClosedChannelException}. If the output is shut down and another thread
* is blocked in a write operation, an {@link AsynchronousCloseException} will
* be thrown to the pending thread.
* </p>
* <p>
* Socket channels are thread-safe, no more than one thread can read or write at
* any given time. The {@code connect(SocketAddress)} and {@code
* finishConnect()} methods are synchronized against each other; when they are
* processing, calls to {@code read} and {@code write} will block.
* </p>
*
* @since Android 1.0
*/
public abstract class SocketChannel extends AbstractSelectableChannel implements
ByteChannel, ScatteringByteChannel, GatheringByteChannel {
static {
Platform.getNetworkSystem().oneTimeInitialization(true);
}
/**
* Constructs a new {@code SocketChannel}.
*
* @param selectorProvider
* an instance of SelectorProvider.
* @since Android 1.0
*/
protected SocketChannel(SelectorProvider selectorProvider) {
super(selectorProvider);
}
/**
* Creates an open and unconnected socket channel.
* <p>
* This channel is created by calling {@code openSocketChannel()} of the
* default {@link SelectorProvider} instance.
* </p>
*
* @return the new channel which is open but unconnected.
* @throws IOException
* if an I/O error occurs.
* @since Android 1.0
*/
public static SocketChannel open() throws IOException {
return SelectorProvider.provider().openSocketChannel();
}
/**
* Creates a socket channel and connects it to a socket address.
* <p>
* This method performs a call to {@code open()} followed by a call to
* {@code connect(SocketAdress)}.
* </p>
*
* @param address
* the socket address to be connected to.
* @return the new connected channel.
* @throws AsynchronousCloseException
* if this channel is closed by another thread while this method
* is executing.
* @throws ClosedByInterruptException
* if another thread interrupts the calling thread while this
* operation is executing. The calling thread will have the
* interrupt state set and the channel will be closed.
* @throws SecurityException
* if there is a security manager and it denies the access of
* {@code address}.
* @throws UnresolvedAddressException
* if the address is not resolved.
* @throws UnsupportedAddressTypeException
* if the address type is not supported.
* @throws IOException
* if an I/O error occurs.
* @since Android 1.0
*/
public static SocketChannel open(SocketAddress address) throws IOException {
SocketChannel socketChannel = open();
if (null != socketChannel) {
socketChannel.connect(address);
}
return socketChannel;
}
/**
* Gets the valid operations of this channel. Socket channels support
* connect, read and write operation, so this method returns
* {@code SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE}.
*
* @return the operations supported by this channel.
* @see java.nio.channels.SelectableChannel#validOps()
* @since Android 1.0
*/
public final int validOps() {
return (SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE);
}
/**
* Returns the socket assigned to this channel, which does not declare any public
* methods that are not declared in {@code Socket}.
*
* @return the socket assigned to this channel.
* @since Android 1.0
*/
public abstract Socket socket();
/**
* Indicates whether this channel's socket is connected.
*
* @return {@code true} if this channel's socket is connected, {@code false}
* otherwise.
* @since Android 1.0
*/
public abstract boolean isConnected();
/**
* Indicates whether this channel's socket is still trying to connect.
*
* @return {@code true} if the connection is initiated but not finished;
* {@code false} otherwise.
* @since Android 1.0
*/
public abstract boolean isConnectionPending();
/**
* Connects this channel's socket with a remote address.
* <p>
* If this channel is blocking, this method will suspend until connecting is
* finished or an I/O exception occurrs. If the channel is non-blocking,
* this method will return {@code true} if the connection is finished at
* once or return {@code false} when the connection must be finished later
* by calling {@code finishConnect()}.
* </p>
* <p>
* This method can be called at any moment and can block other read and
* write operations while connecting. It executes the same security checks
* as the connect method of the {@code Socket} class.
* </p>
*
* @param address
* the address to connect with.
* @return {@code true} if the connection is finished, {@code false}
* otherwise.
* @throws AlreadyConnectedException
* if the channel is already connected.
* @throws ConnectionPendingException
* a non-blocking connecting operation is already executing on
* this channel.
* @throws ClosedChannelException
* if this channel is closed.
* @throws AsynchronousCloseException
* if this channel is closed by another thread while this method
* is executing.
* @throws ClosedByInterruptException
* if another thread interrupts the calling thread while this
* operation is in progress. The calling thread will have the
* interrupt state set and this channel will be closed.
* @throws UnresolvedAddressException
* if the address is not resolved.
* @throws UnsupportedAddressTypeException
* if the address type is not supported.
* @throws SecurityException
* if there is a security manager and it denies the access of
* {@code address}.
* @throws IOException
* if an I/O error occurs.
* @since Android 1.0
*/
public abstract boolean connect(SocketAddress address) throws IOException;
/**
* Completes the connection process initiated by a call of {@code
* connect(SocketAddress)}.
* <p>
* This method returns {@code true} if the connection is finished already
* and returns {@code false} if the channel is non-blocking and the
* connection is not finished yet.
* </p>
* <p>
* If this channel is in blocking mode, this method will suspend and return
* {@code true} when the connection is finished. It closes this channel and
* throws an exception if the connection fails.
* </p>
* <p>
* This method can be called at any moment and it can block other {@code
* read} and {@code write} operations while connecting.
* </p>
*
* @return {@code true} if the connection is successfully finished, {@code
* false} otherwise.
* @throws NoConnectionPendingException
* if the channel is not connected and the connection process
* has not been initiated.
* @throws ClosedChannelException
* if this channel is closed.
* @throws AsynchronousCloseException
* if this channel is closed by another thread while this method
* is executing.
* @throws ClosedByInterruptException
* if another thread interrupts the calling thread while this
* operation is in progress. The calling thread has the
* interrupt state set, and this channel is closed.
* @throws IOException
* if an I/O error occurs.
* @since Android 1.0
*/
public abstract boolean finishConnect() throws IOException;
/**
* Reads bytes from this socket channel into the given buffer.
* <p>
* The maximum number of bytes that will be read is the remaining number of
* bytes in the buffer when the method is invoked. The bytes will be copied
* into the buffer starting at the buffer's current position.
* </p>
* <p>
* The call may block if other threads are also attempting to read from this
* channel.
* </p>
* <p>
* Upon completion, the buffer's position is set to the end of the bytes
* that have been read. The buffer's limit is not changed.
* </p>
*
* @param target
* the byte buffer to receive the bytes.
* @return the number of bytes actually read.
* @throws AsynchronousCloseException
* if another thread closes the channel during the read.
* @throws NotYetConnectedException
* if this channel is not yet connected.
* @throws ClosedByInterruptException
* if another thread interrupts the calling thread while this
* operation is in progress. The interrupt state of the calling
* thread is set and the channel is closed.
* @throws ClosedChannelException
* if this channel is closed.
* @throws IOException
* if another I/O error occurs.
* @since Android 1.0
*/
public abstract int read(ByteBuffer target) throws IOException;
/**
* Reads bytes from this socket channel and stores them in a subset of the
* specified array of buffers. The subset is defined by {@code offset} and
* {@code length}, indicating the first buffer and the number of buffers to
* use. This method attempts to read as many bytes as can be stored in the
* buffer subset from this channel and returns the number of bytes actually
* read.
* <p>
* If a read operation is in progress, subsequent threads will block until
* the read is completed and will then contend for the ability to read.
* </p>
*
* @param targets
* the array of byte buffers into which the bytes will be copied.
* @param offset
* the index of the first buffer to store bytes in.
* @param length
* the maximum number of buffers to store bytes in.
* @return the number of bytes actually read.
* @throws AsynchronousCloseException
* if this channel is closed by another thread during this read
* operation.
* @throws ClosedByInterruptException
* if another thread interrupts the calling thread while this
* operation is in progress. The interrupt state of the calling
* thread is set and the channel is closed.
* @throws ClosedChannelException
* if this channel is closed.
* @throws IndexOutOfBoundsException
* if {@code offset < 0} or {@code length < 0}, or if {@code
* offset + length} is greater than the size of {@code targets}.
* @throws IOException
* if another I/O error occurs.
* @throws NotYetConnectedException
* if this channel is not yet connected.
* @since Android 1.0
*/
public abstract long read(ByteBuffer[] targets, int offset, int length)
throws IOException;
/**
* Reads bytes from this socket channel and stores them in the specified
* array of buffers. This method attempts to read as many bytes as can be
* stored in the buffer array from this channel and returns the number of
* bytes actually read.
* <p>
* If a read operation is in progress, subsequent threads will block until
* the read is completed and will then contend for the ability to read.
* </p>
* <p>
* Calling this method is equivalent to calling {@code read(targets, 0,
* targets.length);}
* </p>
*
* @param targets
* the array of byte buffers into which the bytes will be copied.
* @return the number of bytes actually read.
* @throws AsynchronousCloseException
* if this channel is closed by another thread during this read
* operation.
* @throws ClosedByInterruptException
* if another thread interrupts the calling thread while this
* operation is in progress. The interrupt state of the calling
* thread is set and the channel is closed.
* @throws ClosedChannelException
* if this channel is closed.
* @throws IOException
* if another I/O error occurs.
* @throws NotYetConnectedException
* if this channel is not yet connected.
* @since Android 1.0
*/
public synchronized final long read(ByteBuffer[] targets)
throws IOException {
return read(targets, 0, targets.length);
}
/**
* Writes bytes from the given byte buffer to this socket channel. The
* maximum number of bytes that are written is the remaining number of bytes
* in the buffer when this method is invoked. The bytes are taken from the
* buffer starting at the buffer's position.
* <p>
* The call may block if other threads are also attempting to write to the
* same channel.
* </p>
* <p>
* Upon completion, the buffer's position is updated to the end of the bytes
* that have been written. The buffer's limit is not changed.
* </p>
*
* @param source
* the byte buffer containing the bytes to be written.
* @return the number of bytes actually written.
* @throws AsynchronousCloseException
* if another thread closes the channel during the write.
* @throws ClosedByInterruptException
* if another thread interrupts the calling thread while this
* operation is in progress. The interrupt state of the calling
* thread is set and the channel is closed.
* @throws ClosedChannelException
* if the channel was already closed.
* @throws IOException
* if another I/O error occurs.
* @throws NotYetConnectedException
* if this channel is not connected yet.
* @since Android 1.0
*/
public abstract int write(ByteBuffer source) throws IOException;
/**
* Writes bytes from a subset of the specified array of buffers into this
* socket channel. The subset is defined by {@code offset} and {@code
* length}, indicating the first buffer and the number of buffers to use.
* <p>
* If a write operation is in progress, subsequent threads will block until
* the write is completed and then contend for the ability to write.
* </p>
*
* @param sources
* the array of byte buffers that is the source for bytes written
* to this channel.
* @param offset
* the index of the first buffer in {@code buffers }to get bytes
* from.
* @param length
* the number of buffers to get bytes from.
* @return the number of bytes actually written to this channel.
* @throws AsynchronousCloseException
* if this channel is closed by another thread during this write
* operation.
* @throws ClosedByInterruptException
* if another thread interrupts the calling thread while this
* operation is in progress. The interrupt state of the calling
* thread is set and the channel is closed.
* @throws ClosedChannelException
* if this channel is closed.
* @throws IndexOutOfBoundsException
* if {@code offset < 0} or {@code length < 0}, or if {@code
* offset + length} is greater than the size of {@code sources}.
* @throws IOException
* if another I/O error occurs.
* @throws NotYetConnectedException
* if this channel is not yet connected.
* @since Android 1.0
*/
public abstract long write(ByteBuffer[] sources, int offset, int length)
throws IOException;
/**
* Writes bytes from all the given byte buffers to this socket channel.
* <p>
* Calling this method is equivalent to calling {@code write(sources, 0,
* sources.length);}
* </p>
*
* @param sources
* the buffers containing bytes to write.
* @return the number of bytes actually written.
* @throws AsynchronousCloseException
* if this channel is closed by another thread during this write
* operation.
* @throws ClosedByInterruptException
* if another thread interrupts the calling thread while this
* operation is in progress. The interrupt state of the calling
* thread is set and the channel is closed.
* @throws ClosedChannelException
* if this channel is closed.
* @throws IOException
* if another I/O error occurs.
* @throws NotYetConnectedException
* if this channel is not yet connected.
* @since Android 1.0
*/
public synchronized final long write(ByteBuffer[] sources)
throws IOException {
return write(sources, 0, sources.length);
}
}
|