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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With