Module java.base

Class SocketChannel

所有已实现的接口:
Closeable, AutoCloseable, ByteChannel, Channel, GatheringByteChannel, InterruptibleChannel, NetworkChannel, ReadableByteChannel, ScatteringByteChannel, WritableByteChannel

public abstract class SocketChannel extends AbstractSelectableChannel implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, NetworkChannel
用于面向流的连接套接字的可选择通道。

通过调用此类的open方法之一来创建套接字通道。无参数的open方法打开一个用于Internet协议套接字的套接字通道。open(ProtocolFamily)方法用于为指定协议族的套接字打开套接字通道。不可能为任意预先存在的套接字创建通道。新创建的套接字通道是打开的,但尚未连接。尝试在未连接的通道上调用I/O操作将导致抛出NotYetConnectedException。可以通过调用其connect方法来连接套接字通道;一旦连接,套接字通道保持连接状态直到关闭。可以通过调用其isConnected方法来确定套接字通道是否已连接。

套接字通道支持非阻塞连接: 可以创建套接字通道,并通过connect方法启动建立与远程套接字的链接的过程,以便稍后由finishConnect方法完成。可以通过调用isConnectionPending方法来确定连接操作是否正在进行中。

套接字通道支持异步关闭,类似于在Channel类中指定的异步关闭操作。如果一个线程在套接字的输入端关闭套接字的同时,另一个线程在套接字通道的读操作中被阻塞,那么被阻塞线程中的读操作将在不读取任何字节的情况下完成,并返回-1。如果一个线程在套接字的输出端关闭套接字的同时,另一个线程在套接字通道的写操作中被阻塞,那么被阻塞线程将收到一个AsynchronousCloseException

可以使用setOption方法配置套接字选项。用于Internet协议套接字的套接字通道支持以下选项:

套接字选项
选项名称 描述
SO_SNDBUF 套接字发送缓冲区的大小
SO_RCVBUF 套接字接收缓冲区的大小
SO_KEEPALIVE 保持连接活动
SO_REUSEADDR 重用地址
SO_LINGER 关闭时保持数据存在(仅在阻塞模式下配置时)
TCP_NODELAY 禁用Nagle算法

用于Unix域套接字的套接字通道支持:

套接字选项
选项名称 描述
SO_SNDBUF 套接字发送缓冲区的大小
SO_RCVBUF 套接字接收缓冲区的大小
SO_LINGER 关闭时保持数据存在(仅在阻塞模式下配置时)

还可能支持其他(特定于实现的)选项。

套接字通道可安全用于多个并发线程。它们支持并发读写,尽管在任何给定时间最多只能有一个线程在读取,最多只能有一个线程在写入。connectfinishConnect方法在彼此之间是互斥同步的,而在进行这些方法调用时尝试启动读取或写入操作将会阻塞,直到该调用完成。

自从:
1.4
  • Constructor Details

    • SocketChannel

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

    • open

      public static SocketChannel open() throws IOException
      Internet协议套接字打开套接字通道。

      通过调用系统范围默认的openSocketChannel方法创建新通道。

      返回:
      一个新的套接字通道
      抛出:
      IOException - 如果发生I/O错误
      参见:
    • open

      public static SocketChannel open(ProtocolFamily family) throws IOException
      打开套接字通道。 family参数指定通道套接字的协议族

      通过调用系统范围默认的openSocketChannel(ProtocolFamily)方法创建新通道。

      参数:
      family - 协议族
      返回:
      一个新的套接字通道
      抛出:
      UnsupportedOperationException - 如果不支持指定的协议族。例如,假设参数指定为StandardProtocolFamily.INET6,但平台上未启用IPv6。
      IOException - 如果发生I/O错误
      自从:
      15
      参见:
    • open

      public static SocketChannel open(SocketAddress remote) throws IOException
      打开一个套接字通道并将其连接到远程地址。

      如果远程地址是一个InetSocketAddress,那么此方法的工作方式就像调用open()方法一样,调用结果套接字通道上的connect方法,将remote传递给它,然后返回该通道。

      如果远程地址是一个UnixDomainSocketAddress,那么这将通过使用open(ProtocolFamily)方法并将StandardProtocolFamily.UNIX作为参数来工作,调用结果套接字通道上的connect方法,将remote传递给它,然后返回该通道。

      参数:
      remote - 要连接新通道的远程地址
      返回:
      一个新的、已连接的套接字通道
      抛出:
      AsynchronousCloseException - 如果另一个线程在连接操作进行中关闭了此通道
      ClosedByInterruptException - 如果另一个线程在连接操作进行中中断了当前线程,从而关闭了通道并设置了当前线程的中断状态
      UnresolvedAddressException - 如果给定的远程地址是一个未完全解析的InetSocketAddress
      UnsupportedAddressTypeException - 如果给定远程地址的类型不受支持
      SecurityException - 如果安全管理器已安装并且不允许访问给定的远程端点
      IOException - 如果发生其他I/O错误
      参见:
    • validOps

      public final int validOps()
      返回一个标识此通道支持操作的操作集。

      套接字通道支持连接、读取和写入,因此此方法返回(SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE)

      指定者:
      validOps 在类 SelectableChannel
      返回:
      有效操作集
    • bind

      public abstract SocketChannel bind(SocketAddress local) throws IOException
      将通道的套接字绑定到本地地址。

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

      指定者:
      bind 在接口 NetworkChannel
      API 注意:
      将套接字通道绑定到Unix Domain套接字会创建一个与UnixDomainSocketAddress中文件路径对应的文件。此文件在通道关闭后仍然存在,并且必须在另一个套接字可以绑定到相同名称之前删除。如果通过连接而不先调用bind将套接字通道绑定到Unix Domain套接字,则其套接字是未命名的,文件系统中没有相应的套接字文件。如果通过调用 bind(null)自动绑定套接字通道到Unix Domain套接字,则结果也是未命名套接字。
      实现注意:
      每个平台对Unix Domain套接字名称的最大长度强制执行一个特定于实现的最大长度。此限制在绑定通道时执行。最大长度通常接近且通常不少于100字节。
      参数:
      local - 要绑定套接字的地址,或null以将套接字绑定到自动分配的套接字地址
      返回:
      此通道
      抛出:
      ConnectionPendingException - 如果此通道上已经有一个非阻塞连接操作正在进行
      AlreadyBoundException - 如果套接字已经绑定
      UnsupportedAddressTypeException - 如果给定地址的类型不受支持
      ClosedChannelException - 如果通道已关闭
      IOException - 如果发生其他I/O错误
      SecurityException - 如果已安装安全管理器并且其checkListen方法拒绝了Internet协议套接字的操作,或者对于Unix域套接字地址,如果它拒绝了NetPermission("accessUnixDomainSocket")的操作。
      自从:
      1.7
      参见:
    • setOption

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

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

      一旦关闭读取,通道上的进一步读取将返回-1,表示流的结束。如果连接的输入端已经关闭,则调用此方法不会产生任何效果。

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

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

      一旦关闭写入,进一步尝试向通道写入将抛出ClosedChannelException。如果连接的输出端已经关闭,则调用此方法不会产生任何效果。

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

      public abstract Socket socket()
      检索与此通道关联的套接字。
      返回:
      与此通道关联的套接字
      抛出:
      UnsupportedOperationException - 如果通道的套接字不是Internet协议套接字
    • isConnected

      public abstract boolean isConnected()
      告诉此通道的网络套接字是否已连接。
      返回:
      如果且仅当此通道的网络套接字open并已连接时为true
    • isConnectionPending

      public abstract boolean isConnectionPending()
      指示此通道上是否正在进行连接操作。
      返回:
      true 如果且仅当在此通道上已启动连接操作但尚未通过调用finishConnect方法完成时
    • connect

      public abstract boolean connect(SocketAddress remote) throws IOException
      连接此通道的套接字。

      如果此通道处于非阻塞模式,则调用此方法将启动非阻塞连接操作。如果连接立即建立,如可能发生在本地连接,则此方法返回true。否则,此方法返回false,连接操作必须稍后通过调用finishConnect方法完成。

      如果此通道处于阻塞模式,则调用此方法将阻塞,直到建立连接或发生I/O错误。

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

      对于到Unix域套接字的通道,此方法使用安全管理器的checkPermission方法检查NetPermission ("accessUnixDomainSocket")

      此方法可以随时调用。如果在进行此方法的调用时调用此通道上的读取或写入操作,则该操作将首先阻塞,直到此调用完成。如果连接尝试启动但失败,也就是说,如果此方法的调用引发已检查异常,则通道将被关闭。

      参数:
      remote - 要连接到的远程地址
      返回:
      如果建立了连接,则返回true,如果此通道处于非阻塞模式且连接操作正在进行中,则返回false
      抛出:
      AlreadyConnectedException - 如果此通道已连接
      ConnectionPendingException - 如果此通道上已经有一个非阻塞连接操作正在进行
      ClosedChannelException - 如果此通道已关闭
      AsynchronousCloseException - 如果另一个线程在连接操作进行中关闭此通道
      ClosedByInterruptException - 如果另一个线程在连接操作进行中中断当前线程,从而关闭通道并设置当前线程的中断状态
      UnresolvedAddressException - 如果给定的远程地址是未完全解析的InetSocketAddress
      UnsupportedAddressTypeException - 如果给定的远程地址的类型不受支持
      SecurityException - 如果已安装安全管理器且不允许访问给定的远程端点
      IOException - 如果发生其他I/O错误
    • finishConnect

      public abstract boolean finishConnect() throws IOException
      完成连接套接字通道的连接过程。

      通过将套接字通道置于非阻塞模式,然后调用其connect方法来启动非阻塞连接操作。一旦建立连接或尝试失败,套接字通道将变为可连接状态,可以调用此方法来完成连接序列。如果连接操作失败,则调用此方法将导致抛出适当的IOException

      如果此通道已连接,则此方法不会阻塞,并将立即返回true。如果此通道处于非阻塞模式,则如果连接过程尚未完成,则此方法将返回false。如果此通道处于阻塞模式,则此方法将阻塞,直到连接完成或失败,并且始终会返回true或抛出描述失败的已检查异常。

      此方法可以随时调用。如果在进行此方法的调用时调用此通道上的读取或写入操作,则该操作将首先阻塞,直到此调用完成。如果连接尝试失败,也就是说,如果此方法的调用引发已检查异常,则通道将被关闭。

      返回:
      true 如果此通道的套接字现在已连接
      抛出:
      NoConnectionPendingException - 如果此通道未连接且未启动连接操作
      ClosedChannelException - 如果此通道已关闭
      AsynchronousCloseException - 如果另一个线程在连接操作进行中关闭此通道
      ClosedByInterruptException - 如果另一个线程在连接操作进行中中断当前线程,从而关闭通道并设置当前线程的中断状态
      IOException - 如果发生其他I/O错误
    • getRemoteAddress

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

      如果通道的套接字绑定并连接到Internet协议套接字地址,则返回值的类型为InetSocketAddress

      如果通道的套接字绑定并连接到Unix域套接字地址,则返回的地址为UnixDomainSocketAddress

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

      public abstract int read(ByteBuffer dst) throws IOException
      从接口复制的描述: ReadableByteChannel
      从此通道读取一系列字节到给定的缓冲区中。

      尝试从通道中读取最多r字节,其中r是在调用此方法时缓冲区中剩余的字节数,即dst.remaining()

      假设读取长度为n的字节序列,其中0 <= n <= r。此字节序列将被传输到缓冲区中,以便序列中的第一个字节位于索引p,最后一个字节位于索引p + n - 1,其中p是调用此方法时缓冲区的位置。返回时,缓冲区的位置将等于p + n;其限制不会改变。

      读取操作可能不会填满缓冲区,实际上可能根本不读取任何字节。是否这样做取决于通道的性质和状态。例如,处于非阻塞模式的套接字通道不能读取比立即从套接字输入缓冲区中可用的字节更多的字节;同样,文件通道不能读取比文件中剩余的字节更多的字节。但是,保证如果通道处于阻塞模式且缓冲区中至少还有一个字节,则此方法将阻塞,直到读取至少一个字节。

      此方法可以随时调用。但是,如果另一个线程已经启动了对此通道的读取操作,则调用此方法将阻塞,直到第一个操作完成。

      指定者:
      read 在接口 ReadableByteChannel
      参数:
      dst - 要传输字节的缓冲区
      返回:
      读取的字节数,可能为零,或-1如果通道已到达流的末尾
      抛出:
      NotYetConnectedException - 如果此通道尚未连接
      ClosedChannelException - 如果此通道已关闭
      AsynchronousCloseException - 如果另一个线程在读取操作进行中关闭此通道
      ClosedByInterruptException - 如果另一个线程在读取操作进行中中断当前线程,从而关闭通道并设置当前线程的中断状态
      IOException - 如果发生其他I/O错误
    • read

      public abstract long read(ByteBuffer[] dsts, int offset, int length) throws IOException
      从接口复制的描述: ScatteringByteChannel
      从该通道读取字节序列到给定缓冲区的子序列中。

      调用此方法尝试从该通道读取最多 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],依此类推,直到整个字节序列传输到给定的缓冲区。尽可能多的字节被传输到每个缓冲区中,因此每个更新后的缓冲区的最终位置,除了最后一个更新的缓冲区外,都保证等于该缓冲区的限制。

      此方法可以随时调用。但是,如果另一个线程已经启动了对该通道的读取操作,则此方法的调用将阻塞,直到第一个操作完成。

      指定者:
      read 在接口 ScatteringByteChannel
      参数:
      dsts - 要传输字节的缓冲区
      offset - 要传输字节的第一个缓冲区在缓冲区数组中的偏移量;必须是非负的且不大于 dsts.length
      length - 要访问的缓冲区的最大数量;必须是非负的且不大于 dsts.length - offset
      返回:
      读取的字节数,可能为零,或者如果通道已到达流的末尾,则为 -1
      抛出:
      NotYetConnectedException - 如果此通道尚未连接
      ClosedChannelException - 如果此通道已关闭
      AsynchronousCloseException - 如果另一个线程在读取操作进行中关闭了此通道
      ClosedByInterruptException - 如果另一个线程在读取操作进行中中断了当前线程,从而关闭了通道并设置了当前线程的中断状态
      IOException - 如果发生其他I/O错误
    • read

      public final long read(ByteBuffer[] dsts) throws IOException
      从接口复制的描述: ScatteringByteChannel
      从该通道读取字节序列到给定缓冲区中。

      调用此方法的形式 c.read(dsts) 的行为与调用

          c.read(dsts, 0, dsts.length);
      
      指定者:
      read 在接口 ScatteringByteChannel
      参数:
      dsts - 要传输字节的缓冲区
      返回:
      写入的字节数,可能为零,或者如果通道已到达流的末尾,则为 -1
      抛出:
      NotYetConnectedException - 如果此通道尚未连接
      ClosedChannelException - 如果此通道已关闭
      AsynchronousCloseException - 如果另一个线程在写入操作进行中关闭了此通道
      ClosedByInterruptException - 如果另一个线程在写入操作进行中中断了当前线程,从而关闭了通道并设置了当前线程的中断状态
      IOException - 如果发生其他I/O错误
    • write

      public abstract int write(ByteBuffer src) throws IOException
      从接口复制的描述: WritableByteChannel
      从给定缓冲区向该通道写入字节序列。

      尝试向通道写入最多 r 字节,其中 r 是在调用此方法时缓冲区中剩余字节数,即 src.remaining()

      假设写入了长度为 n 的字节序列,其中 0 <= n <= r。此字节序列将从索引 p 处的缓冲区开始写入,其中 p 是调用此方法时缓冲区的位置;最后一个写入的字节的索引将是 p + n - 1。返回时,缓冲区的位置将等于 p + n;其限制不会改变。

      除非另有说明,写操作将仅在写入所有请求的 r 字节后才返回。某些类型的通道,根据其状态,可能仅写入部分字节或可能根本不写入。例如,非阻塞模式下的套接字通道不能写入超出套接字输出缓冲区中可用字节的字节数。

      此方法可以随时调用。但是,如果另一个线程已经启动了对该通道的写入操作,则此方法的调用将阻塞,直到第一个操作完成。

      指定者:
      write 在接口 WritableByteChannel
      参数:
      src - 要检索字节的缓冲区
      返回:
      写入的字节数,可能为零
      抛出:
      NotYetConnectedException - 如果此通道尚未连接
      ClosedChannelException - 如果此通道已关闭
      AsynchronousCloseException - 如果另一个线程在写入操作进行中关闭了此通道
      ClosedByInterruptException - 如果另一个线程在写入操作进行中中断了当前线程,从而关闭了通道并设置了当前线程的中断状态
      IOException - 如果发生其他I/O错误
    • write

      public abstract long write(ByteBuffer[] srcs, int offset, int length) throws IOException
      从接口复制的描述: GatheringByteChannel
      从给定缓冲区的子序列向该通道写入字节序列。

      尝试向通道写入最多 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] 写入,依此类推,直到整个字节序列被写入。尽可能多的字节从每个缓冲区中写入,因此每个更新后的缓冲区的最终位置,除了最后一个更新的缓冲区外,都保证等于该缓冲区的限制。

      除非另有说明,写操作将仅在写入所有请求的 r 字节后才返回。某些类型的通道,根据其状态,可能仅写入部分字节或可能根本不写入。例如,非阻塞模式下的套接字通道不能写入超出套接字输出缓冲区中可用字节的字节数。

      此方法可以随时调用。但是,如果另一个线程已经启动了对该通道的写入操作,则此方法的调用将阻塞,直到第一个操作完成。

      指定由:
      write 在接口 GatheringByteChannel
      参数:
      srcs - 要检索字节的缓冲区
      offset - 要从中检索字节的第一个缓冲区在缓冲区数组中的偏移量;必须是非负的且不大于srcs.length
      length - 要访问的最大缓冲区数;必须是非负的且不大于srcs.length - offset
      返回:
      写入的字节数,可能为零
      抛出:
      NotYetConnectedException - 如果此通道尚未连接
      ClosedChannelException - 如果此通道已关闭
      AsynchronousCloseException - 如果另一个线程在写操作进行中关闭此通道
      ClosedByInterruptException - 如果另一个线程在写操作进行中中断当前线程,从而关闭通道并设置当前线程的中断状态
      IOException - 如果发生其他I/O错误
    • write

      public final long write(ByteBuffer[] srcs) throws IOException
      从接口复制的描述: GatheringByteChannel
      从给定的缓冲区向此通道写入一系列字节。

      c.write(srcs)形式调用此方法的行为与调用方式完全相同

          c.write(srcs, 0, srcs.length);
      
      指定由:
      write 在接口 GatheringByteChannel
      参数:
      srcs - 要检索字节的缓冲区
      返回:
      写入的字节数,可能为零
      抛出:
      NotYetConnectedException - 如果此通道尚未连接
      ClosedChannelException - 如果此通道已关闭
      AsynchronousCloseException - 如果另一个线程在写操作进行中关闭此通道
      ClosedByInterruptException - 如果另一个线程在写操作进行中中断当前线程,从而关闭通道并设置当前线程的中断状态
      IOException - 如果发生其他I/O错误
    • getLocalAddress

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

      如果通道绑定到互联网协议套接字地址,则此方法的返回值为InetSocketAddress类型。如果设置了安全管理器,则将使用其checkConnect方法以本地地址和-1作为参数来查看操作是否被允许。如果不允许操作,则返回代表回环地址和通道套接字的本地端口的SocketAddress

      如果通道绑定到Unix域套接字地址,则套接字地址为UnixDomainSocketAddress。如果设置了安全管理器,则将调用其checkPermission方法,参数为NetPermission ("accessUnixDomainSocket")。如果不允许操作,则返回一个未命名的UnixDomainSocketAddress

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