Module java.base
Package java.net

Class ServerSocket

java.lang.Object
java.net.ServerSocket
所有已实现的接口:
Closeable, AutoCloseable
直接已知的子类:
SSLServerSocket

public class ServerSocket extends Object implements Closeable
该类实现了服务器套接字。服务器套接字等待网络上的请求。它根据该请求执行某些操作,然后可能向请求者返回结果。

服务器套接字的实际工作由SocketImpl类的实例执行。

ServerSocket类定义了一些方便的方法来设置和获取几个套接字选项。该类还定义了setOptiongetOption方法来设置和查询套接字选项。一个ServerSocket支持以下选项:

套接字选项
选项名称 描述
SO_RCVBUF 套接字接收缓冲区的大小
SO_REUSEADDR 重用地址
还可能支持其他(特定于实现的)选项。
自版本:
1.0
参见:
  • Constructor Details

    • ServerSocket

      protected ServerSocket(SocketImpl impl)
      创建一个具有用户指定的SocketImpl的服务器套接字。
      参数:
      impl - 用于ServerSocket的SocketImpl的实例。
      抛出:
      NullPointerException - 如果impl为null
      SecurityException - 如果设置了安全管理器并且其checkPermission方法不允许NetPermission("setSocketImpl")
      自版本:
      12
    • ServerSocket

      public ServerSocket() throws IOException
      创建一个未绑定的服务器套接字。
      抛出:
      IOException - 打开套接字时发生IO错误。
    • ServerSocket

      public ServerSocket(int port) throws IOException
      创建一个绑定到指定端口的服务器套接字。端口号为0表示端口号是自动分配的,通常是从临时端口范围分配的。然后可以通过调用getLocalPort来检索此端口号。

      传入连接指示(连接请求)的最大队列长度设置为50。如果队列已满并且有连接指示到达,则拒绝连接。

      如果应用程序指定了服务器套接字实现工厂,则将调用该工厂的createSocketImpl方法来创建实际的套接字实现。否则将创建系统默认的套接字实现。

      如果存在安全管理器,则将使用port参数调用其checkListen方法以确保允许该操作。这可能导致SecurityException。

      参数:
      port - 端口号,或0以使用自动分配的端口号。
      抛出:
      IOException - 打开套接字时发生I/O错误。
      SecurityException - 如果存在安全管理器并且其checkListen方法不允许该操作。
      IllegalArgumentException - 如果端口参数超出有效端口值范围(包括0到65535之间的值)。
      参见:
    • ServerSocket

      public ServerSocket(int port, int backlog) throws IOException
      创建一个服务器套接字,并将其绑定到指定的本地端口号,带有指定的积压量。端口号为0表示端口号是自动分配的,通常是从临时端口范围分配的。然后可以通过调用getLocalPort来检索此端口号。

      传入连接指示(连接请求)的最大队列长度设置为backlog参数。如果队列已满并且有连接指示到达,则拒绝连接。

      如果应用程序指定了服务器套接字实现工厂,则将调用该工厂的createSocketImpl方法来创建实际的套接字实现。否则将创建系统默认的套接字实现。

      如果存在安全管理器,则将使用port参数调用其checkListen方法以确保允许该操作。这可能导致SecurityException。 backlog参数是套接字上挂起连接的请求的最大数量。其确切语义是特定于实现的。特别是,实现可能施加最大长度,或者选择完全忽略该参数。提供的值应大于0。如果小于或等于0,则将使用特定于实现的默认值。

      参数:
      port - 端口号,或0以使用自动分配的端口号。
      backlog - 请求的最大连接队列长度。
      抛出:
      IOException - 打开套接字时发生I/O错误。
      SecurityException - 如果存在安全管理器并且其checkListen方法不允许该操作。
      IllegalArgumentException - 如果端口参数超出有效端口值范围(包括0到65535之间的值)。
      参见:
    • ServerSocket

      public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException
      创建具有指定端口、监听队列和本地IP地址绑定的服务器。参数bindAddr可用于多宿主主机上的ServerSocket,该ServerSocket仅接受对其地址之一的连接请求。如果bindAddr为null,则默认接受所有本地地址上的连接请求。端口必须在0到65535之间(包括边界值)。端口号为0意味着端口号将自动分配,通常从短暂端口范围中分配。然后可以通过调用getLocalPort来检索此端口号。

      如果存在安全管理器,则此方法将使用port参数调用其checkListen方法,以确保允许该操作。这可能导致SecurityException。参数backlog是套接字上请求的挂起连接的最大数量。其确切语义是特定于实现的。特别是,实现可能施加最大长度,或者选择完全忽略该参数。提供的值应大于0。如果小于或等于0,则将使用特定于实现的默认值。

      参数:
      port - 端口号,或0以使用自动分配的端口号。
      backlog - 请求的传入连接队列的最大长度。
      bindAddr - 服务器将绑定到的本地InetAddress
      抛出:
      SecurityException - 如果存在安全管理器且其checkListen方法不允许该操作。
      IOException - 如果打开套接字时发生I/O错误。
      IllegalArgumentException - 如果端口参数超出有效端口值范围,即0到65535(包括)之间。
      自版本:
      1.1
      参见:
  • Method Details

    • bind

      public void bind(SocketAddress endpoint) throws IOException
      ServerSocket绑定到特定地址(IP地址和端口号)。

      如果地址为null,则系统将选择一个短暂端口和一个有效的本地地址来绑定套接字。

      参数:
      endpoint - 要绑定到的IP地址和端口号。
      抛出:
      IOException - 如果绑定操作失败,或者套接字已经绑定。
      SecurityException - 如果存在SecurityManager并且其checkListen方法不允许该操作。
      IllegalArgumentException - 如果endpoint是此套接字不支持的SocketAddress子类
      自版本:
      1.4
    • bind

      public void bind(SocketAddress endpoint, int backlog) throws IOException
      ServerSocket绑定到特定地址(IP地址和端口号)。

      如果地址为null,则系统将选择一个短暂端口和一个有效的本地地址来绑定套接字。

      backlog参数是套接字上请求的挂起连接的最大数量。其确切语义是特定于实现的。特别是,实现可能施加最大长度,或者选择完全忽略该参数。提供的值应大于0。如果小于或等于0,则将使用特定于实现的默认值。

      参数:
      endpoint - 要绑定到的IP地址和端口号。
      backlog - 请求的传入连接队列的最大长度。
      抛出:
      IOException - 如果绑定操作失败,或者套接字已经绑定。
      SecurityException - 如果存在SecurityManager并且其checkListen方法不允许该操作。
      IllegalArgumentException - 如果endpoint是此套接字不支持的SocketAddress子类
      自版本:
      1.4
    • getInetAddress

      public InetAddress getInetAddress()
      返回此服务器套接字的本地地址。

      如果套接字在关闭之前已绑定,则此方法在套接字关闭后仍将继续返回本地地址。

      如果设置了安全管理器,则将使用其checkConnect方法,参数为本地地址和-1,来检查是否允许该操作。如果不允许该操作,则返回loopback地址。

      返回:
      绑定到此套接字的地址,如果安全管理器拒绝,则返回回环地址,如果套接字未绑定,则返回null
      参见:
    • getLocalPort

      public int getLocalPort()
      返回此套接字正在侦听的端口号。

      如果套接字在关闭之前已绑定,则此方法在套接字关闭后仍将继续返回端口号。

      返回:
      此套接字正在侦听的端口号,如果套接字尚未绑定,则返回-1。
    • getLocalSocketAddress

      public SocketAddress getLocalSocketAddress()
      返回此套接字绑定到的端点的地址。

      如果套接字在关闭之前已绑定,则此方法在套接字关闭后仍将继续返回端点的地址。

      如果设置了安全管理器,则将使用其checkConnect方法,参数为本地地址和-1,来检查是否允许该操作。如果不允许该操作,则返回表示套接字绑定到的本地端口的SocketAddress

      返回:
      表示此套接字本地端点的SocketAddress,如果安全管理器拒绝,则返回表示回环地址的SocketAddress,如果套接字尚未绑定,则返回null
      自版本:
      1.4
      参见:
    • accept

      public Socket accept() throws IOException
      监听连接并接受连接。该方法将阻塞,直到建立连接。

      在以下情况下,此方法是可中断的

      1. 套接字与关联ServerSocketChannel。在这种情况下,中断接受连接的线程将关闭底层通道,并导致此方法抛出带有中断状态设置的ClosedByInterruptException
      2. 套接字使用系统默认的套接字实现,并且虚拟线程正在接受连接。在这种情况下,中断虚拟线程将导致其唤醒并关闭套接字。然后此方法将抛出带有中断状态设置的SocketException

      创建一个新的Socket s,如果存在安全管理器,则将调用安全管理器的checkAccept方法,参数为s.getInetAddress().getHostAddress()s.getPort(),以确保允许该操作。这可能导致SecurityException。

      实现注意:
      使用系统默认SocketImpl的此类的实例接受具有相同类型SocketImpl的套接字,而不管是否已设置客户端套接字实现工厂
      返回:
      新的Socket
      抛出:
      IOException - 等待连接时发生I/O错误。
      SecurityException - 如果存在安全管理器且其checkAccept方法不允许该操作。
      SocketTimeoutException - 如果先前使用setSoTimeout设置了超时,并且已达到超时。
      IllegalBlockingModeException - 如果此套接字具有关联通道,通道处于非阻塞模式,并且没有准备好接受的连接
      参见:
    • implAccept

      protected final void implAccept(Socket s) throws IOException
      ServerSocket的子类使用此方法来重写accept()以返回它们自己的socket子类。因此,FooServerSocket通常会将此方法交给一个新创建的、未绑定的FooSocket。在implAccept返回时,FooSocket将连接到客户端。

      当使用不是新创建且未绑定的socket调用此方法时,此方法的行为是未指定的。在调用此方法之前设置在给定socket上的任何socket选项可能会在接受连接时保留或不保留。当此socket具有一种SocketImpl类型而给定socket具有完全不同类型的SocketImpl类型时,可能无法接受连接。

      实现注意事项:
      使用系统默认SocketImpl的此类的实例可以接受具有相同类型的SocketImpl的Socket的连接:如果Socket使用自定义SocketImpl,则会抛出IOException。使用自定义SocketImpl的此类的实例无法接受具有系统默认SocketImpl的Socket的连接。
      参数:
      s - Socket
      抛出:
      IllegalBlockingModeException - 如果此socket具有关联的通道,并且通道处于非阻塞模式
      IOException - 如果等待连接时发生I/O错误,或者此socket无法与给定socket接受连接
      自从:
      1.1
    • close

      public void close() throws IOException
      关闭此socket。当前在accept()中阻塞的任何线程将抛出SocketException。

      如果此socket有关联的通道,则通道也将被关闭。

      指定者:
      AutoCloseable接口中的close方法
      指定者:
      Closeable接口中的close方法
      抛出:
      IOException - 在关闭socket时发生I/O错误时
    • getChannel

      public ServerSocketChannel getChannel()
      返回与此socket关联的唯一ServerSocketChannel对象(如果有)。

      如果服务器套接字具有通道,则仅当通道本身是通过ServerSocketChannel.open方法创建的时,服务器套接字才会有一个通道。

      返回:
      与此socket关联的服务器套接字通道,如果此socket不是为通道创建的,则返回null
      自从:
      1.4
    • isBound

      public boolean isBound()
      返回ServerSocket的绑定状态。

      如果在关闭之前绑定了socket,则在关闭socket后此方法将继续返回true。

      返回:
      如果ServerSocket成功绑定到地址,则返回true
      自从:
      1.4
    • isClosed

      public boolean isClosed()
      返回ServerSocket的关闭状态。
      返回:
      如果socket已关闭,则返回true
      自从:
      1.4
    • setSoTimeout

      public void setSoTimeout(int timeout) throws SocketException
      使用指定的超时时间(以毫秒为单位)启用/禁用SO_TIMEOUT。将此选项设置为正超时值后,对于此ServerSocket的accept()调用将仅阻塞此时间量。如果超时到期,则会引发java.net.SocketTimeoutException,尽管ServerSocket仍然有效。超时值为零被解释为无限超时。必须在进入阻塞操作之前启用该选项才能生效。
      参数:
      timeout - 指定的超时时间(以毫秒为单位)
      抛出:
      SocketException - 如果底层协议中存在错误,例如TCP错误
      IllegalArgumentException - 如果timeout为负数
      自从:
      1.1
      参见:
    • getSoTimeout

      public int getSoTimeout() throws IOException
      检索SO_TIMEOUT的设置。0表示选项已禁用(即无限超时)。
      返回:
      SO_TIMEOUT值
      抛出:
      IOException - 如果发生I/O错误
      自从:
      1.1
      参见:
    • setReuseAddress

      public void setReuseAddress(boolean on) throws SocketException
      启用/禁用SO_REUSEADDR套接字选项。

      当TCP连接关闭后,连接可能在关闭后的一段时间内保持超时状态(通常称为TIME_WAIT状态或2MSL等待状态)。对于使用已知套接字地址或端口的应用程序,如果涉及套接字地址或端口的连接处于超时状态,则可能无法将套接字绑定到所需的SocketAddress。

      在使用bind(SocketAddress)绑定套接字之前启用SO_REUSEADDR允许即使以前的连接处于超时状态,也可以绑定套接字到地址。

      创建ServerSocket时,SO_REUSEADDR的初始设置未定义。应用程序可以使用getReuseAddress()来确定SO_REUSEADDR的初始设置。

      在套接字绑定后启用或禁用SO_REUSEADDR时的行为未定义(参见isBound())。

      参数:
      on - 是否启用或禁用套接字选项
      抛出:
      SocketException - 如果启用或禁用SO_REUSEADDR套接字选项时发生错误,或者套接字已关闭
      自从:
      1.4
      参见:
    • getReuseAddress

      public boolean getReuseAddress() throws SocketException
      测试是否启用了SO_REUSEADDR。
      返回:
      一个布尔值,指示SO_REUSEADDR是否已启用。
      抛出:
      SocketException - 如果底层协议中存在错误,例如TCP错误。
      自从:
      1.4
      参见:
    • toString

      public String toString()
      以String形式返回此socket的实现地址和实现端口。

      如果设置了安全管理器,并且此socket已绑定,则将调用其checkConnect方法,参数为本地地址和-1,以查看是否允许操作。如果不允许操作,则返回表示回环地址的InetAddress作为实现地址。

      覆盖:
      Object类中的toString方法
      返回:
      此socket的字符串表示形式。
    • setSocketFactory

      @Deprecated(since="17") public static void setSocketFactory(SocketImplFactory fac) throws IOException
      Deprecated.
      Use a ServerSocketFactory and subclass ServerSocket directly.
      This method provided a way in early JDK releases to replace the system wide implementation of ServerSocket. It has been mostly obsolete since Java 1.4. If required, a ServerSocket can be created to use a custom implementation by extending ServerSocket and using the protected constructor that takes an implementation as a parameter.
      设置应用程序的服务器套接字实现工厂。工厂只能指定一次。

      当应用程序创建新的服务器套接字时,将调用套接字实现工厂的createSocketImpl方法来创建实际的套接字实现。

      将null传递给该方法是一个空操作,除非已经设置了工厂。

      如果存在安全管理器,此方法首先调用安全管理器的checkSetFactory方法以确保允许操作。这可能导致SecurityException。

      参数:
      fac - 所需的工厂
      抛出:
      IOException - 设置套接字工厂时发生I/O错误
      SocketException - 如果工厂已经定义
      SecurityException - 如果存在安全管理器且其checkSetFactory方法不允许操作
      参见:
    • setReceiveBufferSize

      public void setReceiveBufferSize(int size) throws SocketException
      设置ServerSocket接受的套接字的SO_RCVBUF选项的默认建议值。实际设置在接受套接字中的值必须通过在套接字被accept()返回后调用Socket.getReceiveBufferSize()来确定。

      SO_RCVBUF的值用于设置内部套接字接收缓冲区的大小,并设置广告给远程对等方的TCP接收窗口的大小。

      可以随后更改该值,通过调用Socket.setReceiveBufferSize(int)。但是,如果应用程序希望允许大于RFC1323定义的64K字节的接收窗口,则必须在将ServerSocket绑定到本地地址之前在ServerSocket中设置建议值。这意味着,必须使用无参数构造函数创建ServerSocket,然后必须调用setReceiveBufferSize(),最后通过调用bind()将ServerSocket绑定到地址。

      不这样做不会导致错误,并且缓冲区大小可能设置为请求的值,但是从此ServerSocket接受的套接字中的TCP接收窗口将不大于64K字节。

      参数:
      size - 要设置接收缓冲区大小的大小。此值必须大于0。
      抛出:
      SocketException - 如果底层协议中存在错误,如TCP错误。
      IllegalArgumentException - 如果值为0或为负。
      自从:
      1.4
      参见:
    • getReceiveBufferSize

      public int getReceiveBufferSize() throws SocketException
      获取此ServerSocketSO_RCVBUF选项的值,即将用于从此ServerSocket接受的套接字的建议缓冲区大小。

      请注意,实际设置在接受套接字中的值是通过调用Socket.getReceiveBufferSize()确定的。

      返回:
      SocketSO_RCVBUF选项的值。
      抛出:
      SocketException - 如果底层协议中存在错误,如TCP错误。
      自从:
      1.4
      参见:
    • setPerformancePreferences

      public void setPerformancePreferences(int connectionTime, int latency, int bandwidth)
      为此ServerSocket设置性能首选项。

      套接字默认使用TCP/IP协议。一些实现可能提供具有不同性能特征的替代协议,这些协议与TCP/IP不同。当实现从可用协议中进行选择时,此方法允许应用程序表达其自己的偏好,以便如何进行这些权衡。

      性能首选项由三个整数描述,其值表示短连接时间、低延迟和高带宽的相对重要性。整数的绝对值无关紧要;为了选择协议,简单地比较这些值,较大的值表示更强的偏好。例如,如果应用程序更喜欢短连接时间而不是低延迟和高带宽,则可以使用值(1, 0, 0)调用此方法。如果应用程序更喜欢高带宽而不是低延迟,以及低延迟而不是短连接时间,则可以使用值(0, 1, 2)调用此方法。

      在绑定此套接字后调用此方法将不起作用。这意味着为了使用此功能,需要使用无参数构造函数创建套接字。

      参数:
      connectionTime - 表达短连接时间的整数
      latency - 表达低延迟的整数
      bandwidth - 表达高带宽的整数
      自从:
      1.5
    • setOption

      public <T> ServerSocket setOption(SocketOption<T> name, T value) throws IOException
      设置套接字选项的值。
      类型参数:
      T - 套接字选项值的类型
      参数:
      name - 套接字选项
      value - 套接字选项的值。对于某些选项,null值可能有效。
      返回:
      ServerSocket
      抛出:
      UnsupportedOperationException - 如果服务器套接字不支持该选项。
      IllegalArgumentException - 如果值对于该选项无效。
      IOException - 如果发生I/O错误,或者套接字已关闭。
      NullPointerException - 如果name为null
      SecurityException - 如果设置了安全管理器,并且套接字选项需要安全权限,调用者没有所需权限。 StandardSocketOptions不需要任何安全权限。
      自从:
      9
    • getOption

      public <T> T getOption(SocketOption<T> name) throws IOException
      返回套接字选项的值。
      类型参数:
      T - 套接字选项值的类型
      参数:
      name - 套接字选项
      返回:
      套接字选项的值。
      抛出:
      UnsupportedOperationException - 如果服务器套接字不支持该选项。
      IOException - 如果发生I/O错误,或者套接字已关闭。
      NullPointerException - 如果name为null
      SecurityException - 如果设置了安全管理器,并且套接字选项需要安全权限,调用者没有所需权限。 StandardSocketOptions不需要任何安全权限。
      自从:
      9
    • supportedOptions

      public Set<SocketOption<?>> supportedOptions()
      返回此服务器套接字支持的套接字选项集。即使套接字已关闭,此方法仍将继续返回选项集。
      返回:
      此套接字支持的套接字选项集。如果套接字的SocketImpl无法创建,则此集合可能为空。
      自从:
      9