Module java.base

Class AsynchronousSocketChannel

java.lang.Object
java.nio.channels.AsynchronousSocketChannel
所有已实现的接口:
Closeable, AutoCloseable, AsynchronousByteChannel, AsynchronousChannel, Channel, NetworkChannel

public abstract class AsynchronousSocketChannel extends Object implements AsynchronousByteChannel, NetworkChannel
用于面向流的连接套接字的异步通道。

异步套接字通道可以通过两种方式创建。通过调用此类定义的一个 open 方法之一来创建新创建的 AsynchronousSocketChannel。新创建的通道是打开的,但尚未连接。当连接到 AsynchronousServerSocketChannel 的套接字时,将创建连接的 AsynchronousSocketChannel。不可能为任意的、预先存在的 socket 创建异步套接字通道。

通过调用其 connect 方法连接新创建的通道;一旦连接,通道保持连接状态直到关闭。可以通过调用其 getRemoteAddress 方法来确定套接字通道是否连接。在未连接的通道上调用 I/O 操作将导致抛出 NotYetConnectedException

此类型的通道可安全地供多个并发线程使用。它们支持并发读写,尽管任何时候最多只能有一个读操作和一个写操作处于未完成状态。如果一个线程在上一个读操作完成之前启动了读操作,则会抛出 ReadPendingException。类似地,如果在上一个写操作完成之前尝试启动写操作,则会抛出 WritePendingException

可以使用 setOption 方法配置套接字选项。异步套接字通道支持以下选项:

套接字选项
选项名称 描述
SO_SNDBUF 套接字发送缓冲区的大小
SO_RCVBUF 套接字接收缓冲区的大小
SO_KEEPALIVE 保持连接活动
SO_REUSEADDR 重用地址
TCP_NODELAY 禁用 Nagle 算法
还可能支持其他(特定于实现的)选项。

超时

此类定义的 readwrite 方法允许在启动读取或写入操作时指定超时。如果超时在操作完成之前到期,则操作将以异常 InterruptedByTimeoutException 完成。超时可能会使通道或底层连接处于不一致状态。如果实现不能保证从通道读取字节,则将通道置于特定于实现的 错误状态。随后尝试启动 read 操作会导致抛出未指定的运行时异常。类似地,如果 write 操作超时且实现不能保证字节未被写入通道,则进一步尝试向通道 write 会导致抛出未指定的运行时异常。当超时到期时,对于 I/O 操作的 ByteBuffer 或缓冲区序列的状态未定义。应丢弃缓冲区,或者至少要注意确保在通道保持打开状态时不访问缓冲区。所有接受超时参数的方法将小于或等于零的值视为 I/O 操作不超时。

自版本:
1.7
  • Constructor Details

    • AsynchronousSocketChannel

      protected AsynchronousSocketChannel(AsynchronousChannelProvider provider)
      初始化此类的新实例。
      参数:
      provider - 创建此通道的提供程序
  • Method Details

    • provider

      public final AsynchronousChannelProvider provider()
      返回创建此通道的提供程序。
      返回:
      创建此通道的提供程序
    • open

      public static AsynchronousSocketChannel open(AsynchronousChannelGroup group) throws IOException
      打开异步套接字通道。

      通过调用创建组的 openAsynchronousSocketChannel 方法在创建组的 AsynchronousChannelProvider 上创建新通道。如果组参数为 null,则结果通道由系统范围内的默认提供程序创建,并绑定到 默认组

      参数:
      group - 新构造通道应绑定到的组,或对于默认组为 null
      返回:
      新的异步套接字通道
      抛出:
      ShutdownChannelGroupException - 如果通道组已关闭
      IOException - 如果发生 I/O 错误
    • open

      public static AsynchronousSocketChannel open() throws IOException
      打开异步套接字通道。

      此方法返回绑定到 默认组 的异步套接字通道。此方法等效于评估以下表达式:

          open((AsynchronousChannelGroup)null);
      
      返回:
      新的异步套接字通道
      抛出:
      IOException - 如果发生 I/O 错误
    • bind

      public abstract AsynchronousSocketChannel bind(SocketAddress local) throws IOException
      从接口复制的描述: NetworkChannel
      将通道的套接字绑定到本地地址。

      此方法用于在套接字和本地地址之间建立关联。建立关联后,套接字将保持绑定状态,直到通道关闭。如果 local 参数的值为 null,则套接字将绑定到自动分配的地址。

      指定者:
      bind 在接口 NetworkChannel
      参数:
      local - 要绑定套接字的地址,或者null以将套接字绑定到自动分配的套接字地址
      返回值:
      此通道
      抛出:
      ConnectionPendingException - 如果此通道上已经有连接操作正在进行
      AlreadyBoundException - 如果套接字已经绑定
      UnsupportedAddressTypeException - 如果给定地址的类型不受支持
      ClosedChannelException - 如果通道已关闭
      IOException - 如果发生其他I/O错误
      SecurityException - 如果已安装安全管理器并且其checkListen方法拒绝操作
      参见:
    • setOption

      public abstract <T> AsynchronousSocketChannel setOption(SocketOption<T> name, T value) throws IOException
      从接口复制的描述: NetworkChannel
      设置套接字选项的值。
      指定者:
      setOption 在接口 NetworkChannel
      类型参数:
      T - 套接字选项值的类型
      参数:
      name - 套接字选项
      value - 套接字选项的值。对于某些套接字选项,null可能是有效值。
      返回值:
      此通道
      抛出:
      IllegalArgumentException - 如果该值不是此套接字选项的有效值
      ClosedChannelException - 如果此通道已关闭
      IOException - 如果发生I/O错误
      参见:
    • shutdownInput

      public abstract AsynchronousSocketChannel shutdownInput() throws IOException
      无需关闭通道即可关闭读取连接。

      一旦关闭读取,通道上的进一步读取将返回-1,表示流的结束。如果连接的输入端已关闭,则调用此方法不会产生任何效果。对于未完成的读取操作的影响取决于系统,因此未指定。当套接字接收缓冲区中有未读取的数据,或者随后到达数据时,其影响(如果有)也取决于系统。

      返回值:
      该通道
      抛出:
      NotYetConnectedException - 如果此通道尚未连接
      ClosedChannelException - 如果此通道已关闭
      IOException - 如果发生其他I/O错误
    • shutdownOutput

      public abstract AsynchronousSocketChannel shutdownOutput() throws IOException
      无需关闭通道即可关闭写入连接。

      一旦关闭写入,进一步尝试向通道写入将抛出ClosedChannelException。如果连接的输出端已关闭,则调用此方法不会产生任何效果。对于未完成的写入操作的影响取决于系统,因此未指定。

      返回值:
      该通道
      抛出:
      NotYetConnectedException - 如果此通道尚未连接
      ClosedChannelException - 如果此通道已关闭
      IOException - 如果发生其他I/O错误
    • getRemoteAddress

      public abstract SocketAddress getRemoteAddress() throws IOException
      返回此通道的套接字连接的远程地址。

      如果通道绑定并连接到互联网协议套接字地址,则此方法的返回值类型为InetSocketAddress

      返回值:
      远程地址;如果通道的套接字未连接,则为null
      抛出:
      ClosedChannelException - 如果通道已关闭
      IOException - 如果发生I/O错误
    • connect

      public abstract <A> void connect(SocketAddress remote, A attachment, CompletionHandler<Void,? super A> handler)
      连接此通道。

      此方法启动连接此通道的操作。handler参数是在成功建立连接或无法建立连接时调用的完成处理程序。如果无法建立连接,则关闭通道。

      此方法执行与Socket类完全相同的安全检查。也就是说,如果已安装安全管理器,则此方法验证其checkConnect方法是否允许连接到给定远程端点的地址和端口号。

      类型参数:
      A - 附件的类型
      参数:
      remote - 要连接此通道的远程地址
      attachment - 要附加到I/O操作的对象;可以为null
      handler - 用于消耗结果的处理程序
      抛出:
      UnresolvedAddressException - 如果给定的远程地址尚未完全解析
      UnsupportedAddressTypeException - 如果给定的远程地址的类型不受支持
      AlreadyConnectedException - 如果此通道已连接
      ConnectionPendingException - 如果此通道上已经有连接操作正在进行
      ShutdownChannelGroupException - 如果通道组已终止
      SecurityException - 如果已安装安全管理器并且不允许访问给定的远程端点
      参见:
    • connect

      public abstract Future<Void> connect(SocketAddress remote)
      连接此通道。

      此方法启动连接此通道的操作。此方法的行为与connect(SocketAddress, Object, CompletionHandler)方法完全相同,只是不需要指定完成处理程序,而是返回表示挂起结果的FutureFutureget方法在成功完成时返回null

      参数:
      remote - 要连接此通道的远程地址
      返回值:
      表示挂起结果的Future对象
      抛出:
      UnresolvedAddressException - 如果给定的远程地址尚未完全解析
      UnsupportedAddressTypeException - 如果给定的远程地址的类型不受支持
      AlreadyConnectedException - 如果此通道已连接
      ConnectionPendingException - 如果此通道上已经有连接操作正在进行
      SecurityException - 如果已安装安全管理器并且不允许访问给定的远程端点
    • read

      public abstract <A> void read(ByteBuffer dst, long timeout, TimeUnit unit, A attachment, CompletionHandler<Integer,? super A> handler)
      从该通道读取一个字节序列到给定的缓冲区中。

      此方法启动一个异步读取操作,将一个字节序列从该通道读取到给定的缓冲区中。handler参数是一个完成处理程序,在读取操作完成(或失败)时调用。传递给完成处理程序的结果是读取的字节数,如果无法读取任何字节,因为通道已达到流的末尾,则为-1

      如果指定了超时,并且超时在操作完成之前到期,则操作将以异常InterruptedByTimeoutException完成。如果发生超时,并且实现无法保证没有从通道读取字节,或将不会从通道读取字节到给定的缓冲区中,则进一步尝试从通道读取将导致抛出一个不明确的运行时异常。

      否则,此方法的工作方式与AsynchronousByteChannel.read(ByteBuffer,Object,CompletionHandler)方法相同。

      类型参数:
      A - 附件的类型
      参数:
      dst - 要传输字节的缓冲区
      timeout - I/O操作完成的最长时间
      unit - timeout参数的时间单位
      attachment - 要附加到I/O操作的对象;可以为null
      handler - 用于消耗结果的处理程序
      抛出:
      IllegalArgumentException - 如果缓冲区是只读的
      ReadPendingException - 如果在该通道上已经有一个读取操作正在进行
      NotYetConnectedException - 如果该通道尚未连接
      ShutdownChannelGroupException - 如果通道组已终止
    • read

      public final <A> void read(ByteBuffer dst, A attachment, CompletionHandler<Integer,? super A> handler)
      从接口中复制的描述: AsynchronousByteChannel
      从该通道读取一个字节序列到给定的缓冲区中。

      此方法启动一个异步读取操作,将一个字节序列从该通道读取到给定的缓冲区中。handler参数是一个完成处理程序,在读取操作完成(或失败)时调用。传递给完成处理程序的结果是读取的字节数,如果无法读取任何字节,因为通道已达到流的末尾,则为-1

      读取操作可能从通道中读取最多r字节,其中r是在尝试读取时缓冲区中剩余的字节数,即dst.remaining()。当r为0时,读取操作将立即完成,结果为0,而不会启动I/O操作。

      假设读取长度为n的字节序列,其中0 < n <= r。此字节序列将被传输到缓冲区中,使得序列中的第一个字节位于索引p,最后一个字节位于索引p + n - 1,其中p是读取执行时缓冲区的位置。完成后,缓冲区的位置将等于p + n;其限制不会改变。

      缓冲区不适用于多个并发线程使用,因此在操作完成之前应谨慎使用缓冲区。

      此方法可以随时调用。某些通道类型可能不允许在任何给定时间有多个读取操作。如果线程在上一个读取操作完成之前启动了读取操作,则将抛出一个ReadPendingException

      指定者:
      read 在接口 AsynchronousByteChannel
      类型参数:
      A - 附件的类型
      参数:
      dst - 要传输字节的缓冲区
      attachment - 要附加到I/O操作的对象;可以为null
      handler - 完成处理程序
      抛出:
      IllegalArgumentException - 如果缓冲区是只读的
      ReadPendingException - 如果通道不允许有多个未完成的读取操作,并且先前的读取操作尚未完成
      NotYetConnectedException - 如果该通道尚未连接
      ShutdownChannelGroupException - 如果通道组已终止
    • read

      public abstract Future<Integer> read(ByteBuffer dst)
      从接口中复制的描述: AsynchronousByteChannel
      从该通道读取一个字节序列到给定的缓冲区中。

      此方法启动一个异步读取操作,将一个字节序列从该通道读取到给定的缓冲区中。该方法的行为与read(ByteBuffer,Object,CompletionHandler)方法完全相同,只是不是指定完成处理程序,而是返回表示待处理结果的FutureFutureget方法返回读取的字节数,如果无法读取任何字节,因为通道已达到流的末尾,则返回-1

      指定者:
      read 在接口 AsynchronousByteChannel
      参数:
      dst - 要传输字节的缓冲区
      返回:
      表示操作结果的Future
      抛出:
      IllegalArgumentException - 如果缓冲区是只读的
      ReadPendingException - 如果通道不允许有多个未完成的读取操作,并且先前的读取操作尚未完成
      NotYetConnectedException - 如果该通道尚未连接
    • read

      public abstract <A> void read(ByteBuffer[] dsts, int offset, int length, long timeout, TimeUnit unit, A attachment, CompletionHandler<Long,? super A> handler)
      从该通道读取一个字节序列到给定的缓冲区的子序列中。此操作,有时称为散射读取,在实现将数据分组为一个或多个固定长度头部后跟可变长度主体的网络协议时通常很有用。handler参数是一个完成处理程序,在读取操作完成(或失败)时调用。传递给完成处理程序的结果是读取的字节数,如果无法读取任何字节,因为通道已达到流的末尾,则为-1

      此方法启动从该通道读取最多r字节的操作,其中r是给定缓冲区数组的指定子序列中剩余字节的总数,即

          dsts[offset].remaining()
              + dsts[offset+1].remaining()
              + ... + dsts[offset+length-1].remaining()
      
      在尝试读取时。

      假设读取长度为n的字节序列,其中0 < n <= r。此序列的最多dsts[offset].remaining()字节将传输到缓冲区dsts[offset],接下来的最多dsts[offset+1].remaining()字节将传输到缓冲区dsts[offset+1],依此类推,直到整个字节序列传输到给定的缓冲区。尽可能多的字节将传输到每个缓冲区中,因此每个更新的缓冲区的最终位置,除了最后一个更新的缓冲区外,都保证等于该缓冲区的限制。底层操作系统可能对可在I/O操作中使用的缓冲区数量施加限制。如果缓冲区的数量(带有剩余字节)超过此限制,则将使用操作系统允许的最大缓冲区数执行I/O操作。

      如果指定了超时,并且超时在操作完成之前到期,则操作将以异常InterruptedByTimeoutException完成。如果发生超时,并且实现无法保证没有从通道读取字节,或将不会从通道读取字节到给定的缓冲区中,则进一步尝试从通道读取将导致抛出一个不明确的运行时异常。

      类型参数:
      A - 附件的类型
      参数:
      dsts - 要传输字节的缓冲区
      offset - 要传输字节的第一个缓冲区在缓冲区数组中的偏移量;必须是非负数且不大于dsts.length
      length - 要访问的最大缓冲区数;必须是非负数且不大于dsts.length - offset
      timeout - I/O 操作完成的最大时间
      unit - timeout 参数的时间单位
      attachment - 要附加到 I/O 操作的对象;可以为null
      handler - 用于消费结果的处理程序
      抛出:
      IndexOutOfBoundsException - 如果未满足offsetlength参数的前提条件
      IllegalArgumentException - 如果缓冲区是只读的
      ReadPendingException - 如果此通道上已经有读操作正在进行
      NotYetConnectedException - 如果此通道尚未连接
      ShutdownChannelGroupException - 如果通道组已终止
    • write

      public abstract <A> void write(ByteBuffer src, long timeout, TimeUnit unit, A attachment, CompletionHandler<Integer,? super A> handler)
      从给定缓冲区向此通道写入字节序列。

      此方法启动异步写操作,从给定缓冲区向此通道写入字节序列。 handler 参数是在写操作完成(或失败)时调用的完成处理程序。传递给完成处理程序的结果是写入的字节数。

      如果指定了超时,并且超时在操作完成之前过期,则会以异常InterruptedByTimeoutException完成。如果发生超时,并且实现不能保证没有从给定缓冲区写入字节,或者不会从给定缓冲区写入字节,则进一步尝试向通道写入将导致抛出不明确的运行时异常。

      否则,此方法的工作方式与AsynchronousByteChannel.write(ByteBuffer,Object,CompletionHandler)方法相同。

      类型参数:
      A - 附件的类型
      参数:
      src - 要检索字节的缓冲区
      timeout - I/O 操作完成的最大时间
      unit - timeout 参数的时间单位
      attachment - 要附加到 I/O 操作的对象;可以为null
      handler - 用于消费结果的处理程序
      抛出:
      WritePendingException - 如果此通道上已经有写操作正在进行
      NotYetConnectedException - 如果此通道尚未连接
      ShutdownChannelGroupException - 如果通道组已终止
    • write

      public final <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer,? super A> handler)
      从接口复制的描述: AsynchronousByteChannel
      从给定缓冲区向此通道写入字节序列。

      此方法启动异步写操作,从给定缓冲区向此通道写入字节序列。 handler 参数是在写操作完成(或失败)时调用的完成处理程序。传递给完成处理程序的结果是写入的字节数。

      写操作可能向通道写入最多r字节,其中r是缓冲区中剩余字节数,即在尝试写入时的src.remaining()。当r为0时,写操作将立即完成,结果为0,而不会启动 I/O 操作。

      假设写入长度为n的字节序列,其中0 < n <= r。此字节序列将从索引p处的缓冲区开始传输,其中p是执行写操作时缓冲区的位置;最后一个写入的字节的索引将是p + n - 1。完成后,缓冲区的位置将等于p + n;其限制不会改变。

      缓冲区不适用于多个并发线程使用,因此在操作完成之前应谨慎使用缓冲区。

      此方法可以随时调用。某些通道类型可能不允许在任何给定时间有多个写操作。如果线程在上一个写操作完成之前启动写操作,则将抛出WritePendingException

      指定者:
      write 在接口 AsynchronousByteChannel
      类型参数:
      A - 附件的类型
      参数:
      src - 要检索字节的缓冲区
      attachment - 要附加到 I/O 操作的对象;可以为null
      handler - 完成处理程序对象
      抛出:
      WritePendingException - 如果通道不允许有多个未完成的写操作,且先前的写操作尚未完成
      NotYetConnectedException - 如果此通道尚未连接
      ShutdownChannelGroupException - 如果通道组已终止
    • write

      public abstract Future<Integer> write(ByteBuffer src)
      从接口复制的描述: AsynchronousByteChannel
      从给定缓冲区向此通道写入字节序列。

      此方法启动异步写操作,从给定缓冲区向此通道写入字节序列。该方法的行为与write(ByteBuffer,Object,CompletionHandler)方法完全相同,只是不是指定完成处理程序,而是返回表示待处理结果的FutureFutureget方法返回写入的字节数。

      指定者:
      write 在接口 AsynchronousByteChannel
      参数:
      src - 要检索字节的缓冲区
      返回:
      表示操作结果的 Future
      抛出:
      WritePendingException - 如果通道不允许有多个未完成的写操作,且先前的写操作尚未完成
      NotYetConnectedException - 如果此通道尚未连接
    • write

      public abstract <A> void write(ByteBuffer[] srcs, int offset, int length, long timeout, TimeUnit unit, A attachment, CompletionHandler<Long,? super A> handler)
      从给定缓冲区的子序列向此通道写入一系列字节。有时称为聚集写入的此操作在实现将数据分组为一个或多个固定长度标头后跟可变长度主体的网络协议时通常很有用。handler参数是在写入操作完成(或失败)时调用的完成处理程序。传递给完成处理程序的结果是写入的字节数。

      此方法启动对此通道的最多r字节的写入,其中r是给定缓冲区数组的指定子序列中剩余字节数的总和,即

          srcs[offset].remaining()
              + srcs[offset+1].remaining()
              + ... + srcs[offset+length-1].remaining()
      
      在尝试写入时的瞬间。

      假设写入长度为n的字节序列,其中0 < n <= r。此序列的最多前srcs[offset].remaining()字节从缓冲区srcs[offset]写入,接下来的最多srcs[offset+1].remaining()字节从缓冲区srcs[offset+1]写入,依此类推,直到整个字节序列被写入。尽可能多的字节从每个缓冲区写入,因此除了最后一个更新的缓冲区之外,每个更新的缓冲区的最终位置保证等于该缓冲区的限制。底层操作系统可能对可在I/O操作中使用的缓冲区数量施加限制。如果缓冲区的数量(带有剩余字节)超过此限制,则使用操作系统允许的最大缓冲区数量执行I/O操作。

      如果指定了超时并且超时在操作完成之前过期,则会使用异常InterruptedByTimeoutException完成。如果发生超时,并且实现无法保证未写入或将不会从给定缓冲区写入通道,则进一步尝试向通道写入将导致抛出不明确的运行时异常。

      类型参数:
      A - 附件的类型
      参数:
      srcs - 要检索字节的缓冲区
      offset - 要从中检索字节的第一个缓冲区在缓冲区数组中的偏移量;必须是非负的且不大于srcs.length
      length - 要访问的缓冲区的最大数量;必须是非负的且不大于srcs.length - offset
      timeout - I/O操作完成的最长时间
      unit - timeout参数的时间单位
      attachment - 要附加到I/O操作的对象;可以为null
      handler - 用于消耗结果的处理程序
      抛出:
      IndexOutOfBoundsException - 如果未满足offsetlength参数的前提条件
      WritePendingException - 如果此通道上已经有一个写操作正在进行
      NotYetConnectedException - 如果此通道尚未连接
      ShutdownChannelGroupException - 如果通道组已终止
    • getLocalAddress

      public abstract SocketAddress getLocalAddress() throws IOException
      返回此通道的套接字绑定到的套接字地址。

      如果通道绑定到互联网协议套接字地址,则此方法的返回值为类型为InetSocketAddress的值。

      如果设置了安全管理器,则将使用其checkConnect方法,以本地地址和-1作为参数,查看操作是否被允许。如果不允许该操作,则返回代表通道套接字的本地端口的环回地址的SocketAddress

      指定者:
      getLocalAddress 在接口 NetworkChannel
      返回:
      套接字绑定到的SocketAddress,如果安全管理器拒绝,则返回代表环回地址的SocketAddress,如果通道的套接字未绑定,则返回null
      抛出:
      ClosedChannelException - 如果通道已关闭
      IOException - 如果发生I/O错误