6

following this post, I have the same problem and I managed to reproduce it with a simple test cast. I hope that you will be able to help me.

Let me explain, I am sending messages using sockets. Everything is working great as long as I set the so_timeout to be less than two minutes. But if I set it to be more than two minutes the socket is timed out after two minutes. So, if I set the so_timeout to be 10 seconds the socket will be timed out after 10 seconds, but if I set it to be 180 seconds the socket will be timed out after 120 seconds.

Here is a test case:

import java.io.*;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;

/**
 *
 */
public class TestSocket1 {

public static void main(String[] args) throws IOException {

    ServerSocket serverSocket = new ServerSocket();

    serverSocket.setReuseAddress(true);
    serverSocket.bind(new InetSocketAddress(1111), 0);
    serverSocket.setSoTimeout(1000);
    Socket socket = null;

    boolean send = true;

    while (send) {
        try {
            socket = serverSocket.accept();
            Thread.sleep(100);
            String messageReceived = readFromSocket(socket);

            System.out.println(messageReceived);

            if (send) {
                send = false;

                Thread.sleep(150000); // Causing 2.5 minutes delay
                // Sending message

                BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF8"));
                PrintWriter printWriter = new PrintWriter(wr, true);

                String output = "Hello Back";

                printWriter.println(output);
                printWriter.flush();
                socket.shutdownOutput();

            }

        }
        catch (SocketTimeoutException ie) {
        }
        catch (Exception e) {
        }
        finally {
            if (socket != null) {
                socket.close();
            }
        }
    }


}

protected static String readFromSocket(Socket socket) throws IOException {
    StringBuilder messageReceived = new StringBuilder();
    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));

    String line = br.readLine();

    messageReceived.append(line);

    socket.shutdownInput();

    return messageReceived.toString();
}


}

import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;

/**
 *
 */
public class TestSocket2 {

public static void main(String[] args) throws IOException {

    Socket socket = new Socket();
    socket.setKeepAlive(true);
    socket.setReuseAddress(true);
    socket.setTcpNoDelay(true);
    socket.setSoTimeout(180000); // Should wait 3 minutes before throwing time out exception - Actually throwing after 2 minutes

    SocketAddress socketAddress = new InetSocketAddress(1111);

    socket.connect(socketAddress, 5000);

    // Sending message

    BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF8"));
    PrintWriter printWriter = new PrintWriter(wr, true);

    String output = "Hello There";

    printWriter.println(output);
    printWriter.flush();
    socket.shutdownOutput();

    String messageReceived = readFromSocket(socket);

    System.out.println(messageReceived);

}

protected static String readFromSocket(Socket socket) throws IOException {
    StringBuilder messageReceived = new StringBuilder();
    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));

    String line = br.readLine();

    messageReceived.append(line);

    socket.shutdownInput();

    return messageReceived.toString();
}


}

You should run the TestSocket1 class first and then TestSocket2.

I am struggling with this problem for a long time and any help will be appreciated. Thank you.

  • EDIT

So I removed the dependency on SO_TimeOut and took @Nick suggestion in this post to check the available input stream before reading it. But now the problem is that after two minutes the available bytes always return 0 although the input was written to the stream. So I still have the same problem.

Community
  • 1
  • 1
Rotem
  • 2,306
  • 3
  • 26
  • 44
  • I have tested your code on my laptop(OS X 10.8.4, JDK 1.6.0_37) and the `TimeoutException` is thrown after 180 minutes as expected. Could you provide you OS version and JDK version? – ericson Jun 09 '13 at 11:08
  • OS Windows7 Ultimate SP1 64Bit, JDK jdk1.6.0_26. BTW, if you aren't restricted to two minutes you shouldn't see the TimeoutException. Notice that the sleep is for 2.5 minutes and the SoTimeOut is set to 3 minutes so you should see the 'Hello Back' message. – Rotem Jun 09 '13 at 11:32
  • Sorry, I forgot to mention that I'd increased sleep time to 25 minutes to reproduce the `TimeoutException`. I am not familiar with windows platform, hope someone else would help. – ericson Jun 09 '13 at 11:47
  • I hope so too, thank you – Rotem Jun 09 '13 at 11:51
  • Looks like someone had encountered this issue too, you can check the answer in [this post](http://stackoverflow.com/questions/1306119/setsotimeout-on-a-client-socket-doesnt-affect-the-socket). – ericson Jun 09 '13 at 11:54
  • Notice that this is not entire my problem. The SO_TimeOut isn't ignored just restricted to two minutes. If this indeed platform configuration I would like to see any reference for it. What @Nick suggested can be a good idea but I will have to handle the time out myself. – Rotem Jun 09 '13 at 12:10
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/31480/discussion-between-rotem-and-ericson) – Rotem Jun 09 '13 at 12:18

2 Answers2

2

You can't increase the connect timeout beyond the platform default, which is about a minute. You can only decrease it. Trying to increase it doesn't actually make sense. What are you trying to accomplish?

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    Ok, well first I couldn't find any information about the default socket time out in windows I would appreciate if you can add a link. Secondly, the setSoTimeout documentation state _A timeout of zero is interpreted as an infinite timeout_ so how could I know that it is restricted to the platform's default (again, I couldn't find any information about this)? Thirdly, I'm trying to fix a bug in an old system which allow sending messages between sockets that can take more than two minutes. – Rotem Jun 09 '13 at 11:18
  • The Javadoc is obviously wrong about the connect timeout, a rare occasion. If you don't set it at all, or set it to zero, you will definitely get a connect timeout under the appropriate circumstances. However your comment is about the *read* timeout, which is a different thing. You can set a read timeout to anything you like. I've never seen a problem with it, and I use Windows socket read timeouts regularly. – user207421 Jun 10 '13 at 01:20
  • The javadocs is referring to the **read** timeout. If you never had problem with Windows sockets read timeout I would appreciate it if you can run the test case and check for yourself. Thank you. – Rotem Jun 10 '13 at 07:07
  • Here is the javadocs: _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._ – Rotem Jun 10 '13 at 08:15
2

So I figured out what was the problem the

socket.shutdownInput();

cause the socket to change to FIN_WAIT state thus wait 2 minutes before closing (2MSL)

Rotem
  • 2,306
  • 3
  • 26
  • 44