| /* |
| * 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; |
| |
| /** |
| * 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> |
| * 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> |
| * 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. |
| */ |
| public abstract class SocketChannel extends AbstractSelectableChannel implements |
| ByteChannel, ScatteringByteChannel, GatheringByteChannel { |
| |
| /** |
| * Constructs a new {@code SocketChannel}. |
| * |
| * @param selectorProvider |
| * an instance of SelectorProvider. |
| */ |
| 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. |
| * |
| * @return the new channel which is open but unconnected. |
| * @throws IOException |
| * if an I/O error occurs. |
| */ |
| 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(SocketAddress)}. |
| * |
| * @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 UnresolvedAddressException |
| * if the address is not resolved. |
| * @throws UnsupportedAddressTypeException |
| * if the address type is not supported. |
| * @throws IOException |
| * if an I/O error occurs. |
| */ |
| public static SocketChannel open(SocketAddress address) throws IOException { |
| SocketChannel socketChannel = open(); |
| if (socketChannel != null) { |
| 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() |
| */ |
| @Override |
| 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. |
| */ |
| 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. |
| */ |
| 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. |
| */ |
| 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 occurs. 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> |
| * 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. |
| * |
| * @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 IOException |
| * if an I/O error occurs. |
| */ |
| 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> |
| * 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> |
| * This method can be called at any moment and it can block other {@code |
| * read} and {@code write} operations while connecting. |
| * |
| * @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. |
| */ |
| 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> |
| * The call may block if other threads are also attempting to read from this |
| * channel. |
| * <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. |
| * |
| * @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. |
| * @see java.nio.channels.ReadableByteChannel#read(java.nio.ByteBuffer) |
| */ |
| public abstract int read(ByteBuffer target) throws IOException; |
| |
| /** |
| * Reads bytes from this socket channel into a subset of the given buffers. |
| * This method attempts to read all {@code remaining()} bytes from {@code |
| * length} byte buffers, in order, starting at {@code targets[offset]}. The |
| * number of bytes actually read is returned. |
| * <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. |
| * |
| * @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. |
| * @see java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[], |
| * int, int) |
| */ |
| 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> |
| * Calling this method is equivalent to calling {@code read(targets, 0, |
| * targets.length);} |
| * |
| * @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. |
| */ |
| 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> |
| * 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. |
| * |
| * @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. |
| * @see java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer) |
| */ |
| public abstract int write(ByteBuffer source) throws IOException; |
| |
| /** |
| * Attempts to write a subset of the given bytes from the buffers to this |
| * socket channel. This method attempts to write all {@code remaining()} |
| * bytes from {@code length} byte buffers, in order, starting at {@code |
| * sources[offset]}. The number of bytes actually written is returned. |
| * <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. |
| * |
| * @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. |
| * @see java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[], |
| * int, int) |
| */ |
| 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);} |
| * |
| * @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. |
| * @see java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[]) |
| */ |
| public synchronized final long write(ByteBuffer[] sources) throws IOException { |
| return write(sources, 0, sources.length); |
| } |
| } |