58

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

setSoTimeout

public void setSoTimeout(int timeout) 抛出 SocketException

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

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

    mySocket.setSoTimeout(2000);
    

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

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

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

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

4

3 回答 3

49

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

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

超时过期是什么意思?

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

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

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

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

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

于 2013-05-06T12:39:22.770 回答
37

JavaDoc很好地解释了它:

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

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

于 2012-10-10T14:00:58.610 回答
13

这个例子让我明白了一切:
你可以看到 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();
    }
  }
}
于 2012-10-10T14:37:02.417 回答