【问题标题】:What is the functionality of setSoTimeout and how it works?setSoTimeout 的功能是什么以及它是如何工作的?
【发布时间】:2012-10-01 00:21:05
【问题描述】:

我正在尝试自己学习 Socket。我对 Oracle 网站上的以下文字有点困惑。我对此有一些疑问。提前感谢您提供任何明确的解释。

setSoTimeout

public void setSoTimeout(int timeout) 抛出 SocketException

使用指定的超时启用/禁用 SO_TIMEOUT,以毫秒为单位。将此选项设置为非零超时后,对与此 Socket 关联的 InputStreamread() 调用将仅阻塞这段时间。如果超时到期,则会引发 java.net.SocketTimeoutException,尽管 Socket 仍然有效。必须在进入阻塞操作之前启用该选项才能生效。超时必须 > 0。超时为零被解释为无限超时。

  1. 什么是 SO_TIMEOUT?
  2. Socket 是连接的端点。如果我说

    mySocket.setSoTimeout(2000);
    

    这是否意味着我在 2000 毫秒内阻止从服务器/客户端读取此套接字的任何输入,而在此时间之后,套接字已准备好读取数据?

  3. 超时过期是什么意思?

  4. 在阻塞操作之前必须启用什么选项?

  5. 无限超时意味着套接字不再读取?

【问题讨论】:

    标签: java networking connection


    【解决方案1】:

    这是否意味着我在 2000 毫秒内阻止从服务器/客户端读取此套接字的任何输入,而在此时间之后,套接字已准备好读取数据?

    不,这意味着如果在 2000 毫秒内没有数据到达,则会抛出 SocketTimeoutException

    超时过期是什么意思?

    这意味着 2000 毫秒(在您的情况下)过去了,没有任何数据到达。

    在阻塞操作之前必须启用的选项是什么?

    没有一个“必须”启用。如果您的意思是“可能启用”,这就是其中之一。

    无限超时意味着套接字不再读取?

    多么奇怪的建议。这意味着如果没有数据到达,您将永远阻塞读取。

    【讨论】:

    • 不错的答案,尽管套接字 API 没有 SO_TIMEOUT 套接字选项。实现并不是那么简单。
    • 错字?并非如此,SO_TIMEOUT 是对特定于操作系统的机制的抽象。在 Unix 系统上,JVM 使用 poll 或 select。在 Windows 上,它使用仅限 Windows 的 SO_RCVTIMEO 套接字选项。
    • EJP,这个问题是关于 Java 套接字 API 中的SO_TIMEOUT 选项的。如果您研究它是如何实现的(至少在 OpenJDK 中),您会发现 Windows 实现使用 SO_RCVTIMEO,而 Linux/Solaris 实现使用 poll 或 select 来达到相同的效果。比较hg.openjdk.java.net/jdk7/jdk7-gate/jdk/file/9b8c96f96a0f/src/…hg.openjdk.java.net/jdk7/jdk7-gate/jdk/file/9b8c96f96a0f/src/…
    • @Joni 你是这个名字游戏的发起者,让我们准确地完成它。 Java Socket API 中没有 'SO_TIMEOUT 选项。有一个Socket.setSoTimeout() 方法,其Javadoc 不准确地引用SO_TIMEOUT,正如您在第一条评论中正确所说的那样,它不存在。我知道它是如何实施的,我也知道其中的原因。
    • 没有理由必须使用 SO_RCVTIMEO 实现 SO_TIMEOUT。如果您阅读 OpenJDK 7 源代码,您会发现以下注释:SO_TIMEOUT 是用于指定 ServerSocket.accept 和 Socket.getInputStream().read 超时的套接字选项。它通常不映射到本机级别的套接字选项。对于 Windows,我们对此进行特殊处理,并使用 SOL_SOCKET/SO_RCVTIMEO 套接字选项来指定套接字上的接收超时。 在 Linux 和 Solaris 上,它们使用 poll 代替。如果你没有看到讨论 SO_TIMEOUT 是如何实现的意义,你为什么要提出 SO_RCVTIMEO?
    【解决方案2】:

    JavaDoc 解释的很好:

    将此选项设置为非零超时,read() 调用 与此 Socket 关联的 InputStream 将仅针对此阻塞 多少时间。如果超时到期,则 引发了 java.net.SocketTimeoutException,尽管 Socket 仍然存在 有效的。必须在进入阻止之前启用该选项 操作才能生效。超时必须 > 0。超时为零 被解释为无限超时。

    SO_TIMEOUTread() 调用将阻塞的超时时间。如果达到超时,将抛出java.net.SocketTimeoutException。如果您想永久阻塞,将此选项设置为零(默认值),那么read() 调用将阻塞,直到至少可以读取 1 个字节。

    【讨论】:

    • 感谢您的回复,但我仍然不知道超时到期是什么意思?这是否意味着预期的时间过去了。例如:mySocket.setSoTimeout(2000); mySocket 会在 2000 毫秒后过期吗?那么除了零的情况外,总是超时会过期吗?
    • 我只是觉得 setSoTimeout 被命名为 setSoTimeout 而不是 setSocketTimeout 很奇怪,为什么?
    • @tom_mai78101 有时会缩短方法以避免长名称。
    • setSoTimeout() 方法显然是以SO_TIMEOUT 选项命名的。它设置SO_TIMEOUT.
    • 这个值是否仅适用于套接字上没有接收到数据的情况?长期阅读怎么样?仅供参考,我有一个服务电话,我想确保它不会超过 2 秒。这样做是创建一个监视请求的线程的唯一方法吗?
    【解决方案3】:

    这个例子让我明白了一切:
    如您所见, setSoTimeout 防止程序挂起!它等待SO_TIMEOUT时间!如果它没有得到任何信号,它就会抛出异常!这意味着时间已到!

    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.net.SocketTimeoutException;
    
    public class SocketTest extends Thread {
      private ServerSocket serverSocket;
    
      public SocketTest() throws IOException {
        serverSocket = new ServerSocket(8008);
        serverSocket.setSoTimeout(10000);
      }
    
      public void run() {
        while (true) {
          try {
            System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
            Socket client = serverSocket.accept();
    
            System.out.println("Just connected to " + client.getRemoteSocketAddress());
            client.close();
          } catch (SocketTimeoutException s) {
            System.out.println("Socket timed out!");
            break;
          } catch (IOException e) {
            e.printStackTrace();
            break;
          }
        }
      }
    
      public static void main(String[] args) {
        try {
          Thread t = new SocketTest();
          t.start();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    

    【讨论】:

    • 这正是我在回复中所解释的......无论如何,我很高兴,因为你终于明白了这个套接字选项的目的;.))
    • 这也正是它在 Javadoc 中所说的。
    猜你喜欢
    • 1970-01-01
    • 2020-08-06
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-14
    • 2014-01-09
    相关资源
    最近更新 更多