setSoTimeout的功能是什么以及它如何工作?

Ber*_*ard 45 java connection networking

我正试图自己学习Socket.关注Oracle网站上的文字我有点困惑.我对此有一些疑问.提前感谢任何明确的解释.

setSoTimeout

public void setSoTimeout(int timeout)抛出SocketException

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

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

    mySocket.setSoTimeout(2000);
    
    Run Code Online (Sandbox Code Playgroud)

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

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

  4. 在阻止操作之前必须启用哪个选项?

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

use*_*421 36

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

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

超时到期是什么意思?

这意味着2000ms(在您的情况下)过去没有任何数据到达.

在阻止操作之前必须启用哪个选项?

没有一个"必须"启用.如果你的意思是"可以启用",这就是其中之一.

套接字不再读取的无限超时措辞?

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

  • EJP,这个问题是关于*Java socket*API中的`SO_TIMEOUT`选项.如果你研究它是如何实现的(至少在OpenJDK中),你会看到Windows实现使用`SO_RCVTIMEO`,而Linux/Solaris实现使用poll或select来实现相同的效果.比较http://hg.openjdk.java.net/jdk7/jdk7-gate/jdk/file/9b8c96f96a0f/src/solaris/native/java/net/PlainSocketImpl.c和http://hg.openjdk.java.net /jdk7/jdk7-gate/jdk/file/9b8c96f96a0f/src/windows/native/java/net/TwoStacksPlainSocketImpl.c (3认同)
  • 错别字?不是真的,`SO_TIMEOUT` 是对操作系统特定机制的抽象。在 Unix 系统上,JVM 使用轮询或选择。在 Windows 上,它使用 Windows-only `SO_RCVTIMEO` 套接字选项。 (2认同)

log*_*off 30

JavaDoc的解释非常好:

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

SO_TIMEOUTread()呼叫将阻止的超时.如果达到超时,将抛出java.net.SocketTimeoutException.如果要永久阻止将此选项置为零(默认值),则read()调用将阻塞,直到可以读取至少1个字节.

  • `setSoTimeout()`方法显然是以`SO_TIMEOUT`选项命名的.它设置了`SO_TIMEOUT (6认同)
  • 我觉得奇怪的是`setSoTimeout`被命名为`setSoTimeout`而不是`setSocketTimeout`,为什么? (4认同)
  • @tom_mai78101 有时,方法会被缩短以避免长名称。 (2认同)
  • 如果套接字上没有收到数据,此值是否仅适用?长时间阅读怎么样?仅供参考我有一个服务电话,我想确保它不会超过2秒钟.唯一的方法是创建一个监视请求的线程吗? (2认同)

Ber*_*ard 12

这个例子让我一切都清楚:
你可以看到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();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这正是我在回复中解释的......无论如何,我很高兴,因为你终于理解了这个套接字选项的目的;.)) (2认同)