Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Socket read timeout under windows: strange hardcode in native method

I was trying to grasp how socket read timeout is processed in native code and found some strange hardcoded value of 5000 milliseconds there:

if (timeout) {
    if (timeout <= 5000 || !isRcvTimeoutSupported) {
        int ret = NET_Timeout (fd, timeout);
        .....
        .....
    }
}

Source: http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/windows/native/java/net/SocketInputStream.c

As I can see, the variable isRcvTimeoutSupported is generally set to true, but could be dropped to false when setting socket options:

    /*
     * SO_RCVTIMEO is only supported on Microsoft's implementation
     * of Windows Sockets so if WSAENOPROTOOPT returned then
     * reset flag and timeout will be implemented using
     * select() -- see SocketInputStream.socketRead.
     */

    if (isRcvTimeoutSupported) {
        jclass iCls = (*env)->FindClass(env, "java/lang/Integer");
        jfieldID i_valueID;
        jint timeout;

        CHECK_NULL(iCls);
        i_valueID = (*env)->GetFieldID(env, iCls, "value", "I");
        CHECK_NULL(i_valueID);
        timeout = (*env)->GetIntField(env, value, i_valueID);

        /*
         * Disable SO_RCVTIMEO if timeout is <= 5 second.
         */

        if (timeout <= 5000) {
            timeout = 0;
        }


        if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
            sizeof(timeout)) < 0) {

            if (WSAGetLastError() == WSAENOPROTOOPT) {
                isRcvTimeoutSupported = JNI_FALSE;
            } else {
                NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO");
            }

        }
        ......
        ......
    }

Source: http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/windows/native/java/net/TwoStacksPlainSocketImpl.c

While I'm not quite sure, it looks like read timeout is supposed to be set through socket options when higher than 5 seconds and through NET_Timeout if less or equal to 5 seconds. Is it correct?

And anyway, where these hardcoded 5 seconds come from?
I do not see any explanation on MSDN.

like image 354
user3714601 Avatar asked Mar 07 '18 14:03

user3714601


People also ask

How do I fix socket timeout exception?

Using try/catch/finally If you are a developer, so you can surround the socket connection part of your code in a try/catch/finally and handle the error in the catch. You might try connecting a second time, or try connecting to another possible socket, or simply exit the program cleanly.

Why does socket read timed out?

From the client side, the “read timed out” error happens if the server is taking longer to respond and send information. This could be due to a slow internet connection, or the host could be offline.

How do I fix SocketTimeoutException read timed out?

A possible solution for this problem within the Tomcat web application is to modify the CONTEXT. XML file, and modify the CONNECTOR definition that governs the workstation browser connectivity to the Tomcat server. Specifically, modify the connectionTimeout value. Increase this value to suppress the error condition.

How do I fix Java net SocketTimeoutException connect timed out?

As stated the error cannot be solved by the client, since it is a network related issue. However, what you can do is retry connecting a few times. This may work as a workaround until the real issue is fixed. Save this answer.


1 Answers

This code decides how to implement a blocking socket timeout -- whether to do it with SO_RCVTIMEO or with select, as Windows sockets support both (SO_RCVTIMEO is not supported on all platforms, and not even all Windows implementations may support it as noted in the code comment). NET_Timeout uses select under the covers.

Basically the algorithm is:

if SO_RCVTIMEO is supported and timeout is more than 5 seconds:
    use SO_RCVTIMEO
else:
    use select

As to where the 5 seconds threshold comes from, my best guess is that they somehow figured out (through testing or trial and error?) that select is more reliable or more accurate for timeout values less than 5 seconds. Not that it's related specifically to this issue (it is for a different OS), but here is an example of somebody reporting that SO_RCVTIMEO is unreliable for small timeout values.

like image 122
mnistic Avatar answered Oct 21 '22 23:10

mnistic