57

I'm trying to learn Socket by myself. I'm little bit confused by following text from Oracle website. I have some questions regarding that. Thanks in advance for any clear explanation.

setSoTimeout

public void setSoTimeout(int timeout) throws SocketException

Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds. With this option set to a non-zero timeout, a read() call on the InputStream associated with this Socket will block for only this amount of time. If the timeout expires, a java.net.SocketTimeoutException is raised, though the Socket is still valid. The option must be enabled prior to entering the blocking operation to have effect. The timeout must be > 0. A timeout of zero is interpreted as an infinite timeout.

  1. What is SO_TIMEOUT?
  2. Socket is the endpoint of a connection. If I say

    mySocket.setSoTimeout(2000);
    

    Does it mean that I'm blocking reading any input from the Server/Client for this socket for 2000 millisecond and after this time the socket is ready to read data?

  3. What does it mean timeout expire?

  4. What is the option which must be enabled prior to blocking operation?

  5. Infinite Timeout means that the socket does't read anymore?

logoff
  • 3,118
  • 4
  • 36
  • 51
Bernard
  • 3,880
  • 18
  • 49
  • 82

3 Answers3

45

Does it mean that I'm blocking reading any input from the Server/Client for this socket for 2000 millisecond and after this time the socket is ready to read data?

No, it means that if no data arrives within 2000ms a SocketTimeoutException will be thrown.

What does it mean timeout expire?

It means the 2000ms (in your case) elapses without any data arriving.

What is the option which must be enabled prior to blocking operation?

There isn't one that 'must be' enabled. If you mean 'may be enabled', this is one of them.

Infinite Timeout menas that the socket does't read anymore?

What a strange suggestion. It means that if no data ever arrives you will block in the read forever.

user207421
  • 289,834
  • 37
  • 266
  • 440
  • Nice answer, though the sockets API does not have an `SO_TIMEOUT` socket option. The implementation is not so straightforward. – Joni May 27 '13 at 10:41
  • Oops, typo city somewhere ;-( – user207421 May 27 '13 at 11:22
  • 2
    Typo? Not really, `SO_TIMEOUT` is an abstraction over OS-specific mechanisms. On Unix systems the JVM uses poll or select. On Windows it uses the Windows-only `SO_RCVTIMEO` socket option. – Joni May 27 '13 at 12:24
  • @Joni It can't be an 'abstraction' and non-existent at the same time. Unix and Linux both have SO_RCVTIMEO defined, although it doesn't actually do anything in some of them. I was using it 20 years ago. I don't know what 'the implementation is not so straightforward' means. Your point is getting increasingly obscure. – user207421 May 30 '13 at 08:38
  • 3
    EJP, this question is about the `SO_TIMEOUT` option in the *Java socket* API. If you study how it is implemented (at least in OpenJDK) you'll see that the Windows implementation uses `SO_RCVTIMEO`, while the Linux/Solaris implementation uses poll or select to achieve the same effect. Compare http://hg.openjdk.java.net/jdk7/jdk7-gate/jdk/file/9b8c96f96a0f/src/solaris/native/java/net/PlainSocketImpl.c and http://hg.openjdk.java.net/jdk7/jdk7-gate/jdk/file/9b8c96f96a0f/src/windows/native/java/net/TwoStacksPlainSocketImpl.c – Joni May 30 '13 at 09:57
  • 1
    @Joni You're the one who started this name game, let's finish it accurately. *There is no* '`SO_TIMEOUT` option in the Java `Socket` API. There is a `Socket.setSoTimeout()` *method,* whose [Javadoc](http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#setSoTimeout(int)) inaccurately refers to `SO_TIMEOUT`, which as you correctly said in your first comment is non-existent. I'm aware of how it's implemented and I'm aware of the reasons why. – user207421 May 31 '13 at 11:21
  • To see that there is an `SO_TIMEOUT` option you can read the *text* of the documentation for `setSoTimeout` ("Enable/disable SO_TIMEOUT with the specified timeout"), and refer to http://docs.oracle.com/javase/7/docs/api/java/net/SocketOptions.html#SO_TIMEOUT, but, whatever. – Joni May 31 '13 at 11:23
  • @Joni The exact point of your endless quibbling and self-contradiction over whether `SO_TIMEOUT` exists escapes me. The same statement about `SO_TIMEOUT` appears in the [1.4 documentation](http://docs.oracle.com/javase/1.4.2/docs/api/java/net/Socket.html#setSoTimeout(int)) years before `SocketOptions.SO_TIMEOUT` had any public existence. – user207421 May 31 '13 at 11:29
  • The original "quib" was to correct your statement that `SO_TIMEOUT` was a part of the *BSD* socket API. Your corrected answer implies `SO_TIMEOUT` does not exist in *any* socket API. What I'm trying to point out now is that `SO_TIMEOUT` is a socket option in the Java socket API, as you can read in the API spec, and that it's not equivalent to the `SO_RCVTIMEO` option in the BSD API. – Joni May 31 '13 at 11:59
  • @Joni Whatever its abstract/existence/non-existence status may be, it is implemented on most platforms via the SO_RCVTIMEO option, and therefore 100% equivalent. The point of all this escapes me. – user207421 Oct 19 '13 at 03:31
  • 1
    There's no reason why SO_TIMEOUT must be implemented using SO_RCVTIMEO. If you read the OpenJDK 7 source code you'll find this comment: *SO_TIMEOUT is the socket option used to specify the timeout for ServerSocket.accept and Socket.getInputStream().read. It does not typically map to a native level socket option. For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO socket option to specify a receive timeout on the socket.* On Linux and Solaris they use `poll` instead. If you don't see the point in discussing how SO_TIMEOUT is implemented why do you bring up SO_RCVTIMEO? – Joni Oct 19 '13 at 10:41
  • @Joni I didn't say that SO_TIMEOUT either must be or was implemented via SO_RCVTIMEO. I said that it is 'on most platforms'. If you want to refute me, make sure it's something I've actually said. – user207421 Dec 17 '13 at 08:24
  • Fine. First, "on most platforms." What data do you have to support that claim? As you know, OpenJDK uses RCVTIMEO on Windows, and other mechanisms on Linux and Solaris, and one out of three is not "most." Second, "therefore 100% equivalent." The SO_TIMEOUT option also sets the timeout for `ServerSocket.accept` and, as you are well aware, no BSD API socket option does that. – Joni Dec 17 '13 at 10:23
  • @Joni That would be a great argument if those were the only three platforms. They aren't. – user207421 Apr 05 '18 at 09:47
  • The accepted answer bascially indicates that the SO_TIMEOUT is the time that the socket will read for. But this answer says it's the time it will read for after getting no response. Quite different. So if I set it to say 2 seconds, according to your answer as long as I'm still receiving a constant stream of packets, the socket could theoretically never time out. Whereas the accepted answer basically says the socket will listen for 2 seconds then timeout. So, I'm wondering which it is. Or have I missed something. Thanks in advance. – grolschie May 14 '20 at 23:14
36

The JavaDoc explains it very well:

With this option set to a non-zero timeout, a read() call on the InputStream associated with this Socket will block for only this amount of time. If the timeout expires, a java.net.SocketTimeoutException is raised, though the Socket is still valid. The option must be enabled prior to entering the blocking operation to have effect. The timeout must be > 0. A timeout of zero is interpreted as an infinite timeout.

SO_TIMEOUT is the timeout that a read() call will block. If the timeout is reached, a java.net.SocketTimeoutException will be thrown. If you want to block forever put this option to zero (the default value), then the read() call will block until at least 1 byte could be read.

logoff
  • 3,118
  • 4
  • 36
  • 51
  • Thanks for your reply but I still don't know what does it mean the timeout expires? Does it mean that the expected time passed. For instance: mySocket.setSoTimeout(2000); mySocket will be expired after 2000 millisecond? So always timeout will be expire except the zero situation? – Bernard Oct 10 '12 at 14:05
  • It means that your Socket InputStream has not any byte available to read, that means no bytes have been sent to the Socket. – logoff Oct 10 '12 at 14:06
  • 7
    I just find it weird that `setSoTimeout` is named as `setSoTimeout` and not `setSocketTimeout`, why? – tom_mai78101 Nov 19 '12 at 13:29
  • 2
    @tom_mai78101 sometimes, methods are shortened to avoid long names. – logoff Nov 20 '12 at 08:04
  • 6
    The `setSoTimeout()` method is obviously named after the `SO_TIMEOUT` option. It sets `SO_TIMEOUT.` – user207421 May 06 '13 at 12:40
  • 5
    Does this value ONLY apply to if no data has been received on the socket? What about a long running read? FYI I have a service call that I want to make sure it doesn't take any longer than 2 seconds. Is the only way to do that to create a thread that monitors the request? – Kevin M Apr 10 '14 at 16:12
  • @KevinM The only way a read can be 'long-running' is if no data arrives. Your question embodies a distinction without a difference. The correct way remains `setSoTimeout()`. – user207421 Feb 19 '17 at 05:01
13

This example made everything clear for me:
As you can see setSoTimeout prevent the program to hang! It wait for SO_TIMEOUT time! if it does not get any signal it throw exception! It means that time expired!

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();
    }
  }
}
Bernard
  • 3,880
  • 18
  • 49
  • 82